From patchwork Thu Jun 1 16:22:25 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789212 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=j1hIPnAY; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBKv1FyRz20QH for ; Fri, 2 Jun 2023 02:24:35 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 19E6986351; Thu, 1 Jun 2023 18:24:32 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="j1hIPnAY"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 2931C8633F; Thu, 1 Jun 2023 18:24:30 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-io1-xd31.google.com (mail-io1-xd31.google.com [IPv6:2607:f8b0:4864:20::d31]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id A97CC8615F for ; Thu, 1 Jun 2023 18:24:27 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd31.google.com with SMTP id ca18e2360f4ac-7777bf2c285so1916139f.2 for ; Thu, 01 Jun 2023 09:24:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636666; x=1688228666; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=+nZbIHWn0Lqw+7sIznfNqxtoq42+e+7eretzJP+1CqM=; b=j1hIPnAY7ExYBa604MQT2d56Y0L+pS0N98bTT8q92as+FSkU3PpCyf/+A9vtldEG9M rl1LNlqZk/1GbKCM5gCK72r3zZtLx5vwaxt+bLS4WKbA3jAt+002dJhbnNeIeoksv1pA Z53oZqZDgDYPxakotITJzw6cqIaNWevRlbbCk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636666; x=1688228666; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=+nZbIHWn0Lqw+7sIznfNqxtoq42+e+7eretzJP+1CqM=; b=PgLuJWuUNFAIiKiE7X0arE1+3ggKH0FabtNLr1gw3oQhI2ftxNJH+S8WPHJvpfdwn1 Zt97aruGiSZj3PLyA1oXM5PZUv99JfqfnyReyoQqF3mntkwWOAfvfMLPo3PcSF9SEksY 6ooh+51u1BoUT/hbk5ZlHgn6Da8jwyodT59JK9a7IO+FrD1clIEptuLQxw1h05sWxzX/ gVb8PpRGq3+iowTnB5cG78dR90q3b0v7Bnapr+3H7v1LDlDgBI+GbFICCPcd5nrPAcqQ 9PUxGNH7Sfg3zj/G9ct0/Mq3BTe2aYY3C88rRZHxBdbwmFw/8bDU/q9zKXNE2IDdgXJU FuiQ== X-Gm-Message-State: AC+VfDwnk+ZFyDGlnVpw0HTK0JxNP4I9CY4sWLFEgsNUfr8zeL61WiZI 6yyyolsJ85Q7zKlYaj2Ji5mGtH6agNB46hXnwC4= X-Google-Smtp-Source: ACHHUZ4HybRGQnQx6ktMFT1C+Tbgt0ELNIgM+DBjR55IoABLEECUN1B+uMRxVMRyQ3ifjf6iyuPtQQ== X-Received: by 2002:a05:6e02:6c9:b0:33b:1b4c:69e1 with SMTP id p9-20020a056e0206c900b0033b1b4c69e1mr6458109ils.17.1685636666211; Thu, 01 Jun 2023 09:24:26 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:25 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass , Alper Nebi Yasak , Jan Kiszka , Neha Malcom Francis , Peng Fan , Philippe Reynes , Stefan Herbrechtsmeier Subject: [PATCH 01/40] binman: Correct coverage gap in control Date: Thu, 1 Jun 2023 10:22:25 -0600 Message-ID: <20230601162404.220488-2-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Add a pragma to deal with the code-coverage gap which drops binman down to 90% coverage. Fixes: de65b122a25 (tools: Fall back to importlib_resources on Python 3.6) Signed-off-by: Simon Glass --- tools/binman/control.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/binman/control.py b/tools/binman/control.py index 68597c4e7792..7e2dd3541b96 100644 --- a/tools/binman/control.py +++ b/tools/binman/control.py @@ -9,7 +9,7 @@ from collections import OrderedDict import glob try: import importlib.resources -except ImportError: +except ImportError: # pragma: no cover # for Python 3.6 import importlib_resources import os From patchwork Thu Jun 1 16:22:26 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789213 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=KLsbsxhG; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBLC1xQyz20QH for ; Fri, 2 Jun 2023 02:24:51 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id E34228634C; Thu, 1 Jun 2023 18:24:35 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="KLsbsxhG"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 437D68634C; Thu, 1 Jun 2023 18:24:31 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x133.google.com (mail-il1-x133.google.com [IPv6:2607:f8b0:4864:20::133]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 80DAB86327 for ; Thu, 1 Jun 2023 18:24:28 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x133.google.com with SMTP id e9e14a558f8ab-33bbb78248fso4223505ab.0 for ; Thu, 01 Jun 2023 09:24:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636667; x=1688228667; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=DiVKdFbb/CoQkot5ygItHS0JyBO9jOlB6sNF8u1JZMs=; b=KLsbsxhG7fDUOtptYMO9DsMiOTvIl7N8n1WQ5yR+IAfn2F32wAE1OJhuAj4ljglyfU STVeDHtfdxxedqelGNpq8k+Nalozt3fRo3LzCL29jT5XIvADvzaWYkY1KhGQc46KHCpi dlp9rC3+HA5CzbKnc71w1FLXsW9jVZIXN0utw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636667; x=1688228667; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=DiVKdFbb/CoQkot5ygItHS0JyBO9jOlB6sNF8u1JZMs=; b=HNp4b8hanZcXfxG+y+ifczFgJ+iXi2awZZumqSqzXDG1DGkRskzhqK2f8s/hzeaOUO AiKN26V7JqD4einWH4ixn+YDZvZPowb9FAERbQ4EsKEdqUWg0vHLdB0AjyZchlgChtgH to/V6AFQtBQMUsmlbExY25rYdoOQLOkGCvzmUa5k07zIJLgHWiFKACj8a4t1qU775ymL z+/CkS2XY5BOH9vYt7xlIPXb+0HdcybSTSsH+wyV0mq6WSp9RYZjszImIHm/Nns1GPj+ sT7vaBeLQXpnKNGeeVBdaRfupLKqkOmLXULXdNmDnoqt8RMsuW06KqMDi5Jp7d3eBmry 3lLQ== X-Gm-Message-State: AC+VfDzZHe2d6B53TkBC6FvKckJkPVt6xCgFt1gfmPtV9Nrran51n4fN kMOm7LkUoloYDlgeDhiAibksmIPIePMqZxBjgNg= X-Google-Smtp-Source: ACHHUZ57Q13I1UkHnPKAuVTsPKNLK5/vGS12OFieAJCaQUS/gbUjMdeRObE/oPVfHfHfnIPknEbwWg== X-Received: by 2002:a92:d410:0:b0:33b:c0d8:26af with SMTP id q16-20020a92d410000000b0033bc0d826afmr6540032ilm.7.1685636667049; Thu, 01 Jun 2023 09:24:27 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:26 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 02/40] expo: Correct some header-file comments Date: Thu, 1 Jun 2023 10:22:26 -0600 Message-ID: <20230601162404.220488-3-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean The use of Returns instead of @return still confuses me. Fix some problems that have crept in. Signed-off-by: Simon Glass --- boot/scene_internal.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/boot/scene_internal.h b/boot/scene_internal.h index e8fd765811e1..9f173dd749f0 100644 --- a/boot/scene_internal.h +++ b/boot/scene_internal.h @@ -23,7 +23,7 @@ struct scene *expo_lookup_scene_id(struct expo *exp, uint scene_id); * * @exp: Expo to use * @id: ID to use, or 0 to auto-allocate one - * @return: Either @id, or the auto-allocated ID + * Returns: Either @id, or the auto-allocated ID */ uint resolve_id(struct expo *exp, uint id); @@ -36,6 +36,7 @@ uint resolve_id(struct expo *exp, uint id); * @scn: Scene to search * @id: ID of object to find * @type: Type of the object, or SCENEOBJT_NONE to match any type + * Returns: Object found, or NULL if not found */ void *scene_obj_find(struct scene *scn, uint id, enum scene_obj_t type); @@ -62,6 +63,7 @@ int scene_obj_add(struct scene *scn, const char *name, uint id, * * @scn: Scene to update * @menu: Menu to process + * Returns: 0 if OK, -ve on error */ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu); @@ -72,7 +74,7 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu); * @menu: Menu to use * @key: Key code to send (KEY_...) * @event: Place to put any event which is generated by the key - * @return 0 if OK, -ENOTTY if there is no current menu item, other -ve on other + * Returns: 0 if OK, -ENOTTY if there is no current menu item, other -ve on other * error */ int scene_menu_send_key(struct scene *scn, struct scene_obj_menu *menu, int key, @@ -89,7 +91,7 @@ void scene_menu_destroy(struct scene_obj_menu *menu); * scene_menu_display() - Display a menu as text * * @menu: Menu to display - * @return 0 if OK, -ENOENT if @id is invalid + * Returns: 0 if OK, -ENOENT if @id is invalid */ int scene_menu_display(struct scene_obj_menu *menu); From patchwork Thu Jun 1 16:22:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789214 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=IJdSNNo/; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBLW3VH4z20Py for ; Fri, 2 Jun 2023 02:25:07 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 63A6986335; Thu, 1 Jun 2023 18:24:38 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="IJdSNNo/"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id C287E86339; Thu, 1 Jun 2023 18:24:33 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x12b.google.com (mail-il1-x12b.google.com [IPv6:2607:f8b0:4864:20::12b]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 8A8798633C for ; Thu, 1 Jun 2023 18:24:29 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x12b.google.com with SMTP id e9e14a558f8ab-33b1da9a8acso4143225ab.3 for ; Thu, 01 Jun 2023 09:24:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636668; x=1688228668; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=sH1MStrfrc0dITNI61OOiPcdt1ZzQlPVTttqvWuPOoI=; b=IJdSNNo/uM3mTOax6ET06mepxGoIJizv7NnMuQ/I3hY3y2W0H+o2BwLuGieGdtnq+a 1S4wKKamux6xZRqpCPMMPdJ63IiMME90zgJ4LmetlRLki2FNFuVJEzGJLfp7x+VJyuTk KnY2NFHaquBOm0OLqa5g1jzRaTGkl3CzolWe4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636668; x=1688228668; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=sH1MStrfrc0dITNI61OOiPcdt1ZzQlPVTttqvWuPOoI=; b=Vg3nW5tKVsFPE2YK4/dW6r9F7y8edzzazEKHw+SYTg9Dc9AuweZjyD46IT1AS7cbGA NXVNPypnFc9xTUgbKMH4i+7jeHjSoIzIee6jV+nc1r0EoQP6okfUDECpT9nlmbxTbU6c 5/54ULMXW5OkpsJLjNYe42RnHdemiWB5uflSw9R617ncYC0N2D/VI0A7yvp7+RwlW462 8RGW6DHE2v+NzWhcuO0WCH84Rq3/8UwjDnkz35nS3TFotODcCC+fNcCzS6qfGBnCEZGw H9gHD5Quo0BrAeTEqj3BtuUQAIHyGGjCI2yTDAYiG9QYH0DAiCWqwFxD8WIA7Z3WKohJ VzhA== X-Gm-Message-State: AC+VfDyfGqh7ITLphzkzV93zQnNLdQck5wLiRABewfgQrb2n3W24eoHa BD3Uc3WVrrAI4ymDkFPGDep/dixkaHqH1cjBdLQ= X-Google-Smtp-Source: ACHHUZ5aNWo5LTXQP0JVoUWkkoFs8EitCyIQz6Rv7WopgyqzE9s2pIWpuXchmMzmLAd75O+DU2vWBg== X-Received: by 2002:a92:cf02:0:b0:338:d50f:f5e2 with SMTP id c2-20020a92cf02000000b00338d50ff5e2mr6356894ilo.18.1685636668070; Thu, 01 Jun 2023 09:24:28 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:27 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 03/40] expo: Convert to using a string ID for the scene title Date: Thu, 1 Jun 2023 10:22:27 -0600 Message-ID: <20230601102257.3.I2cf67d2d512c67904f8f1b9df25e8d8dcdfd01d2@changeid> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean This is easier to deal with if it uses the existing string handling, since we will be able to use translations, etc. in the future. Update it to use an ID instead of a string. Signed-off-by: Simon Glass --- boot/scene.c | 8 ++------ include/expo.h | 10 +++++----- test/boot/expo.c | 19 ++++++++++--------- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/boot/scene.c b/boot/scene.c index 030f6aa2a0a9..d2f77c008cf7 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -65,16 +65,12 @@ void scene_destroy(struct scene *scn) scene_obj_destroy(obj); free(scn->name); - free(scn->title); free(scn); } -int scene_title_set(struct scene *scn, const char *title) +int scene_title_set(struct scene *scn, uint id) { - free(scn->title); - scn->title = strdup(title); - if (!scn->title) - return log_msg_ret("tit", -ENOMEM); + scn->title_id = id; return 0; } diff --git a/include/expo.h b/include/expo.h index d242f48e30c7..8827f4b0b45f 100644 --- a/include/expo.h +++ b/include/expo.h @@ -92,7 +92,7 @@ struct expo_string { * @expo: Expo this scene is part of * @name: Name of the scene (allocated) * @id: ID number of the scene - * @title: Title of the scene (allocated) + * @title_id: String ID of title of the scene (allocated) * @sibling: Node to link this scene to its siblings * @obj_head: List of objects in the scene */ @@ -100,7 +100,7 @@ struct scene { struct expo *expo; char *name; uint id; - char *title; + uint title_id; struct list_head sibling; struct list_head obj_head; }; @@ -338,10 +338,10 @@ struct scene *expo_lookup_scene_id(struct expo *exp, uint scene_id); * scene_title_set() - set the scene title * * @scn: Scene to update - * @title: Title to set, NULL if none (this is allocated by this call) - * Returns: 0 if OK, -ENOMEM if out of memory + * @title_id: Title ID to set + * Returns: 0 if OK */ -int scene_title_set(struct scene *scn, const char *title); +int scene_title_set(struct scene *scn, uint title_id); /** * scene_obj_count() - Count the number of objects in a scene diff --git a/test/boot/expo.c b/test/boot/expo.c index 7104dff05e8d..3c0bc78bb7a4 100644 --- a/test/boot/expo.c +++ b/test/boot/expo.c @@ -28,6 +28,8 @@ enum { OBJ_MENU_TITLE, /* strings */ + STR_SCENE_TITLE, + STR_TEXT, STR_TEXT2, STR_MENU_TITLE, @@ -120,7 +122,7 @@ static int expo_scene(struct unit_test_state *uts) struct expo *exp; ulong start_mem; char name[100]; - int id; + int id, title_id; start_mem = ut_check_free(); @@ -141,21 +143,20 @@ static int expo_scene(struct unit_test_state *uts) ut_asserteq_str(SCENE_NAME1, scn->name); /* Set the title */ - strcpy(name, SCENE_TITLE); - ut_assertok(scene_title_set(scn, name)); - *name = '\0'; - ut_assertnonnull(scn->title); - ut_asserteq_str(SCENE_TITLE, scn->title); + title_id = expo_str(exp, "title", STR_SCENE_TITLE, SCENE_TITLE); + ut_assert(title_id >= 0); - /* Use an allocated ID */ + /* Use an allocated ID - this will be allocated after the title str */ scn = NULL; id = scene_new(exp, SCENE_NAME2, 0, &scn); ut_assertnonnull(scn); - ut_asserteq(SCENE2, id); - ut_asserteq(SCENE2 + 1, exp->next_id); + ut_assertok(scene_title_set(scn, title_id)); + ut_asserteq(STR_SCENE_TITLE + 1, id); + ut_asserteq(STR_SCENE_TITLE + 2, exp->next_id); ut_asserteq_ptr(exp, scn->expo); ut_asserteq_str(SCENE_NAME2, scn->name); + ut_asserteq(title_id, scn->title_id); expo_destroy(exp); From patchwork Thu Jun 1 16:22:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789215 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=fP9us7TS; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBLm07xjz20Py for ; Fri, 2 Jun 2023 02:25:20 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 54B908633C; Thu, 1 Jun 2023 18:24:40 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="fP9us7TS"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id A0EE886334; Thu, 1 Jun 2023 18:24:34 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x134.google.com (mail-il1-x134.google.com [IPv6:2607:f8b0:4864:20::134]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 593AF8615F for ; Thu, 1 Jun 2023 18:24:30 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x134.google.com with SMTP id e9e14a558f8ab-33b4b70693eso4244225ab.1 for ; Thu, 01 Jun 2023 09:24:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636669; x=1688228669; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=vob1NO6gdLAu9ZiFaTQljyEOCjRamHqxc5ztPZOqbEE=; b=fP9us7TSouc1RDucGzEScG3A5ZuBVR3C6qGPPkAT0c1uvzdPFC50+W7geu/7SBfQBf hJZGe7DxCsn0m9ZINW6AeI579lF76zyQofWSex25fUCFMN3u2Gb3g3hn88V0itjno5lH ihrn3kZeSCtG82ll713EXWWrelrtVLYeJF6T4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636669; x=1688228669; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=vob1NO6gdLAu9ZiFaTQljyEOCjRamHqxc5ztPZOqbEE=; b=da1mkC/FUREElbuq6HI0nvdB/2i2DkGA+9Gl6ukHCDX5k4QtAibUAobHwtRvx/UUi1 WHr0umi3z4tboXMSgLQjlUVZppx9V2dUJvtmubTiuDAw7XSXAcpA/WwjFs3YBR50Zb2y o1BO9rmwofj7jlBJdL1+cSYtgpL03r7I28i/3gpjDmDpxutEYUodPMoZxVViK2E9u8n3 Fldvqwov4HtexaS68wpzIuRUX4Nnnkh5CeOoJDTE2eIfbB3Iw2QgSE51siZdzBOb7eeF 0qqIxH+Tr1T1MGXRfHtwkXeTtYPYxMSZnlhU4NWKYClWdaoyQyawJkJnETNmx64heydI cMFA== X-Gm-Message-State: AC+VfDyLb2Wuf05Cm2iO4kzVyog2PzlAywqSgzOJ6Xke/HzIpyK3ZvfG sa8us5a4EZR3GkBLjKbngy/5XzAT1GYZD/1sh3I= X-Google-Smtp-Source: ACHHUZ5oh0+uanEXF+15Iogr8CObsPr7M8hFznQxZPierYMexwrwBMJ7yQuyQRR07BwlvrLG95brTQ== X-Received: by 2002:a92:d492:0:b0:33b:dfef:909c with SMTP id p18-20020a92d492000000b0033bdfef909cmr6545587ilg.31.1685636668905; Thu, 01 Jun 2023 09:24:28 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:28 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 04/40] sandbox: Fix quiting when the LCD window is closed Date: Thu, 1 Jun 2023 10:22:28 -0600 Message-ID: <20230601102257.4.Icc4af734ed817c02ade1e0033fc588a778dbc99f@changeid> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean With recent changes to how sandbox handles reset, closing the window currently just restarts sandbox. Use the correct sysreset type to tell it to shut down. Signed-off-by: Simon Glass --- arch/sandbox/cpu/sdl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/sandbox/cpu/sdl.c b/arch/sandbox/cpu/sdl.c index 2c570ed8d164..590e406517bf 100644 --- a/arch/sandbox/cpu/sdl.c +++ b/arch/sandbox/cpu/sdl.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -81,7 +82,7 @@ static void sandbox_sdl_poll_events(void) switch (event.type) { case SDL_QUIT: puts("LCD window closed - quitting\n"); - reset_cpu(); + sysreset_walk(SYSRESET_POWER_OFF); break; } } From patchwork Thu Jun 1 16:22:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789216 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=f04JpyyA; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBM24JC8z20Py for ; Fri, 2 Jun 2023 02:25:34 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 8C8F88634E; Thu, 1 Jun 2023 18:24:42 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="f04JpyyA"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 83CFF8632B; Thu, 1 Jun 2023 18:24:36 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-io1-xd29.google.com (mail-io1-xd29.google.com [IPv6:2607:f8b0:4864:20::d29]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 5574486354 for ; Thu, 1 Jun 2023 18:24:31 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd29.google.com with SMTP id ca18e2360f4ac-775abb74a7cso70188239f.0 for ; Thu, 01 Jun 2023 09:24:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636670; x=1688228670; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=aB13LVTnO3taePsYYYe1LrsY4Aj1BUHv47pOSP8gxvo=; b=f04JpyyAxf34P/DppiHHnBHfNTrijREnpwaLyRch0WUYF+NFXywWRpUvYu7wlwzyo5 apSg9leBKaYKodgAvTQ7+5u/HRYI7RXhnESGcaqrUVzqLc4heuLOaR/n13Hqbge5AMjL V5RUDDd4QOoY+M7OZmEV5443Cl6gTjhbQAI/8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636670; x=1688228670; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=aB13LVTnO3taePsYYYe1LrsY4Aj1BUHv47pOSP8gxvo=; b=IxCqeyuA8u2l+dWfI6bDzANVV5wsVjxl96TUsN/tGJkws7cd+wicdRnjpfA6crJPhV Nz5Lpr2gngNjH66hvIIE9SfT1gB41jsAkKEDcVSdEVXNVehBR03N+uJ9xSgW/L265hci KqcojCrLYFJOvndx8Zbw7+dp/Vk1nLEuiwXFX34/0f8DgYMjhpNe+lC2v/UylRCU5VXX d4462zxMsiRkXb42S90Q3dBSI45eYLRgxHgF4PALCy9F+yIolxLrJycgV3jcEfTutVOo gHIPUV6CaBQwvEPD0qA8T6CpXtC+E0HYPLqcKTnkaWObmKQAWOLIpMveA37NJ6GUV25k MWtA== X-Gm-Message-State: AC+VfDyJlsMkSg9iTKbCzQn38iDXEWNzDxhwUOXJxyc5ft2c4skKs45y DfXZEPAUhkV/ETw5G96MHMsfKm9jHGFBZYqSBLo= X-Google-Smtp-Source: ACHHUZ78u4MgWk43LciNRVXPflTbVjZJlKYud3MpK/Hl9gY4yjZXa8RKGHxbe5sGpwjTrWAF9IjO4A== X-Received: by 2002:a92:dc50:0:b0:32a:798e:5e80 with SMTP id x16-20020a92dc50000000b0032a798e5e80mr2772209ilq.0.1685636669684; Thu, 01 Jun 2023 09:24:29 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:29 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 05/40] test: Restore test behaviour on failure Date: Thu, 1 Jun 2023 10:22:29 -0600 Message-ID: <20230601162404.220488-4-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean A recent change makes test continue to run after failure. This results in a lot of useless output and may lead to a segfault. Fix this by adding back the 'return' statement. Fixes: fa847bb409d ("test: Wrap assert macros in ({ ... }) and fix") Signed-off-by: Simon Glass --- include/test/ut.h | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/include/test/ut.h b/include/test/ut.h index dddf9ad241fe..ea6ee95d7344 100644 --- a/include/test/ut.h +++ b/include/test/ut.h @@ -130,7 +130,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); \ if (!(cond)) { \ ut_fail(uts, __FILE__, __LINE__, __func__, #cond); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -142,7 +142,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); if (!(cond)) { \ ut_failf(uts, __FILE__, __LINE__, __func__, #cond, \ fmt, ##args); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -157,7 +157,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); #expr1 " == " #expr2, \ "Expected %#x (%d), got %#x (%d)", \ _val1, _val1, _val2, _val2); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -175,7 +175,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); (unsigned long long)_val1, \ (unsigned long long)_val2, \ (unsigned long long)_val2); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -189,7 +189,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); ut_failf(uts, __FILE__, __LINE__, __func__, \ #expr1 " = " #expr2, \ "Expected \"%s\", got \"%s\"", _val1, _val2); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -208,7 +208,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); #expr1 " = " #expr2, \ "Expected \"%.*s\", got \"%.*s\"", \ _len, _val1, _len, _val2); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -228,7 +228,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); #expr1 " = " #expr2, \ "Expected \"%s\", got \"%s\"", \ __buf1, __buf2); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -242,7 +242,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); ut_failf(uts, __FILE__, __LINE__, __func__, \ #expr1 " = " #expr2, \ "Expected %p, got %p", _val1, _val2); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -257,7 +257,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); ut_failf(uts, __FILE__, __LINE__, __func__, \ #expr1 " = " #expr2, \ "Expected %lx, got %lx", _val1, _val2); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -271,7 +271,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); ut_failf(uts, __FILE__, __LINE__, __func__, \ #expr " != NULL", \ "Expected NULL, got %p", _val); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -285,7 +285,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); ut_failf(uts, __FILE__, __LINE__, __func__, \ #expr " = NULL", \ "Expected non-null, got NULL"); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -300,7 +300,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); #expr " = NULL", \ "Expected pointer, got error %ld", \ PTR_ERR(_val)); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -316,7 +316,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); ut_failf(uts, __FILE__, __LINE__, __func__, \ "console", "\nExpected '%s',\n got '%s'", \ uts->expect_str, uts->actual_str); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -329,7 +329,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); ut_failf(uts, __FILE__, __LINE__, __func__, \ "console", "\nExpected '%s',\n got '%s'", \ uts->expect_str, uts->actual_str); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -341,7 +341,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); if (ut_check_skipline(uts)) { \ ut_failf(uts, __FILE__, __LINE__, __func__, \ "console", "\nExpected a line, got end"); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -354,7 +354,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); ut_failf(uts, __FILE__, __LINE__, __func__, \ "console", "\nExpected '%s',\n got to '%s'", \ uts->expect_str, uts->actual_str); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -367,7 +367,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); ut_failf(uts, __FILE__, __LINE__, __func__, \ "console", "Expected no more output, got '%s'",\ uts->actual_str); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) @@ -381,7 +381,7 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); "console", \ "Expected dump of length %x bytes, got '%s'", \ total_bytes, uts->actual_str); \ - __ret = CMD_RET_FAILURE; \ + return CMD_RET_FAILURE; \ } \ __ret; \ }) From patchwork Thu Jun 1 16:22:30 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789217 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=CC/K87Au; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBMK3Yc6z20Py for ; Fri, 2 Jun 2023 02:25:49 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id A7AE38636B; Thu, 1 Jun 2023 18:24:45 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="CC/K87Au"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 14BAE86354; Thu, 1 Jun 2023 18:24:37 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mail-il1-x12b.google.com (mail-il1-x12b.google.com [IPv6:2607:f8b0:4864:20::12b]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 134DB86347 for ; Thu, 1 Jun 2023 18:24:31 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x12b.google.com with SMTP id e9e14a558f8ab-33b1da9a8acso4143315ab.3 for ; Thu, 01 Jun 2023 09:24:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636670; x=1688228670; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=VUE4b2cfub6CYabePqkHrY+HhlHmeXntUp9dJwzLpxE=; b=CC/K87AuiatOLf01sXpRL+GaJJ/3rstNdYSXW1iDXF6yPQh2BKRVcaINHN1lNGbWpt 0qHu06vOrawKA3V73gLiUrwoXi4HtEa9Zp5Y8gdySSf/7FsXgPZSrZDZOwlm1z5HPGnQ 5qgi+GyF75StmeSVk1QDCk593lN+cNRE4vHq8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636670; x=1688228670; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=VUE4b2cfub6CYabePqkHrY+HhlHmeXntUp9dJwzLpxE=; b=BXN2weZOTT+7P8mZcqTRsgvp7QDGjI2/vYJ794T1qjaau3vdZylxSlKHEhkE6DNjmX 6eD5GuNoKjsR6BeQrFMI/VdvCgiGQGEuOyuwE/5pUaT35BkHViOYaJncucRI1ZZA7pUv YZl2oHV6ajeFZQyOx2WReTYkBBXxKOYGBXK3hR29HuQOtbXj05pXajbLeWgvU/aZd/yJ JeEUbCTTYShmr1ZxRXqHo/Z3RLiRimLxmNY9mSiC5DqR1Vy7JuHPA9pI0wLpwxaV3dBI Hwl2VoGoTtDXajMc638WO7NcZH2N7SAInH1SnrWJe9eAvwBaS+W+N9YZyMgQkQMRAeBX 4ytg== X-Gm-Message-State: AC+VfDxtxsVhwJd3p6KF6l/UOnuIDybdriCrinLNVUB0pt74rWkIuXII tGLXE9PEnAxkT88Fa6McjGunjfwfQptDb7l9to4= X-Google-Smtp-Source: ACHHUZ74RIOAubfFR3aCzugDsZYiWaXtl82xZ2iQw63lIDGbSIdBaSHW3vVxSYq7fIR3OuPx5B+5ew== X-Received: by 2002:a92:db51:0:b0:330:f7b3:ead with SMTP id w17-20020a92db51000000b00330f7b30eadmr6535494ilq.12.1685636670601; Thu, 01 Jun 2023 09:24:30 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:30 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass , Heiko Schocher Subject: [PATCH 06/40] gpio: Avoid using an invalid ofnode Date: Thu, 1 Jun 2023 10:22:30 -0600 Message-ID: <20230601162404.220488-5-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Devices do not necessarily have nodes attached to them, since they can be created from platdata. In SPL a devicetree may in fact not exist at all. Check the node before using it. This avoids failure when OF_CHECKS is enabled. Signed-off-by: Simon Glass Fixes: 5fc7cf8c8e2 ("gpio: add gpio-hog support") Reviewed-by: Heiko Schocher --- drivers/gpio/gpio-uclass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index 712119c3415b..31027f3d9902 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -1474,7 +1474,7 @@ static int gpio_post_bind(struct udevice *dev) } #endif - if (CONFIG_IS_ENABLED(GPIO_HOG)) { + if (CONFIG_IS_ENABLED(GPIO_HOG) && dev_has_ofnode(dev)) { struct udevice *child; ofnode node; From patchwork Thu Jun 1 16:22:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789218 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=dj6USN6U; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBMb5jg1z20Py for ; Fri, 2 Jun 2023 02:26:03 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 2AFD78637B; Thu, 1 Jun 2023 18:24:48 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="dj6USN6U"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 9B8F18632B; Thu, 1 Jun 2023 18:24:37 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mail-io1-xd35.google.com (mail-io1-xd35.google.com [IPv6:2607:f8b0:4864:20::d35]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 545F586335 for ; Thu, 1 Jun 2023 18:24:33 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd35.google.com with SMTP id ca18e2360f4ac-7748edd6c87so2799139f.0 for ; Thu, 01 Jun 2023 09:24:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636671; x=1688228671; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=goEH/fZPr0Sm++zDtXA4AusDcKh/CKRkKNnZKxzb21M=; b=dj6USN6U58XguJelEVQnS+Fo1HWSdpr6gHMYYmGC+Im8b8Xr9LTAKJgxSmEhadJeov AZuy/bc4CKiHffxMkI8Oyi6rcwjclMab5/NRfqiFaa/ogDMq6IJ9u6FI5sGq+LvioNn5 2ZFbHsqxic61Zp9SAdzJZGKXWrCYuzV85QkGY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636671; x=1688228671; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=goEH/fZPr0Sm++zDtXA4AusDcKh/CKRkKNnZKxzb21M=; b=T0e7nfpZVs+DzKlUDwx/NQ4RSihocFWiHrwlDL4zr9a3i9hPYgvI6E33+1umZmwEo3 25ng4NxgTCn1ejHz1Pgcrx1gPyMLJDENQzNjeo9xF73xuJ+FnZzeZwzYltJs9jbXF/jw LgZIBHDqeefgUhkIzUfE+ON+ubRLlH6nlkyf/NkNdNjkFGtkjVtOFuRiomMxHDjanNpd MRvziy1EcNJCjD3Kp3T32IoONNNMy1vRwVe71gdaTz6ylWcXseIIkJahPbmCXb7h8dFf wGnjZEtgyMZxWL8NnWaaiKXgn97icw73g1xQ5MceEE4a9PF+b1iiJ3rueuwUTjEURNAe 3ZfA== X-Gm-Message-State: AC+VfDxiZYC3x/KeKEen4vONXryrzxAqCV73NXhuOI2RbEzKarawOa09 H7oSig2rQjqtBdCQQHtDg7qr8euqOgZHX19pNlk= X-Google-Smtp-Source: ACHHUZ66H2Ase0qMcZdlkwmvC4Xj4FGl2ok04dhKWWEXkkuA0fracTZORshQbkxGamLHyGXkyrEqvw== X-Received: by 2002:a92:d292:0:b0:325:da54:ae8b with SMTP id p18-20020a92d292000000b00325da54ae8bmr4833812ilp.9.1685636671507; Thu, 01 Jun 2023 09:24:31 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:31 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass , Marek Vasut , Pavel Herrmann Subject: [PATCH 07/40] dm: core: Avoid registering an inaccessible tree Date: Thu, 1 Jun 2023 10:22:31 -0600 Message-ID: <20230601162404.220488-6-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean At present there are various restrictions on the use of livetree: - It is only available once the tree is unflattened, i.e. after relocation - It is designed to be used with the control FDT - It can (in principle) be used with other FDTs, but only if they are unflattened first; this is not supported Add a few checks to make sure that any tree that is created is actually valid. Otherwise it can be confusing when nodes and properties cannot actually be accessed. Signed-off-by: Simon Glass --- drivers/core/ofnode.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index ec574c446079..1d4ab5bb6f2f 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -60,6 +60,11 @@ static oftree oftree_ensure(void *fdt) return oftree_null(); } + if (of_live_active()) { + log_err("Cannot register a flattree when OF_LIVE is active\n"); + return oftree_null(); + } + /* register the new tree */ i = oftree_count++; oftree_list[i] = fdt; @@ -133,6 +138,10 @@ oftree oftree_from_fdt(void *fdt) if (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE)) return oftree_ensure(fdt); +#ifdef OF_CHECKS + if (of_live_active()) + return oftree_null(); +#endif tree.fdt = fdt; return tree; From patchwork Thu Jun 1 16:22:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789219 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=XD8e/TYI; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBMt3CXJz20Py for ; Fri, 2 Jun 2023 02:26:18 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id AF53E86362; Thu, 1 Jun 2023 18:24:51 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="XD8e/TYI"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 7B0C48636B; Thu, 1 Jun 2023 18:24:39 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x135.google.com (mail-il1-x135.google.com [IPv6:2607:f8b0:4864:20::135]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 8511086339 for ; Thu, 1 Jun 2023 18:24:34 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x135.google.com with SMTP id e9e14a558f8ab-33cb82122c7so3641535ab.1 for ; Thu, 01 Jun 2023 09:24:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636672; x=1688228672; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=4cOjcwwydYnzsZoT4ZGc3WOVF3z39eo2DADSTkql+kE=; b=XD8e/TYITPk4piFEpFrBH5rlGsF1Qn7KybbwJOspQL3nqtJRupQT+q4v6cNF5QYv/d D0HhmL2TONPWFcsCSnRmgMOFlhGISkzimMz1EKMTCBTiinbhrXPydGwCCOWzAOv6qayX ijfjFkIVQHsVQxeJRKsM9oGNoZBsat9Tb9sbg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636672; x=1688228672; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=4cOjcwwydYnzsZoT4ZGc3WOVF3z39eo2DADSTkql+kE=; b=a6akFjrmTA4LtSM+ZXhiHu3FPicS7v5HM1qdQ9mrmuo5owaMd0OyATLJjZDCF8IjZR jozjeOzsTLXINndkpNQDb50S8Km0ITot6aZIQ0DnsdLAOpQn+iETsgjj0c4+Jq4fGd9b t3fZaRbhxIBt1wQB7Q6l4G6llMZWb9RGwPtAweTnRevKOS37F6hfViQb9LSBmumm0a0S uPagnrgFTzZVyvIdvH5ua1gpO78MCkinz1CCOpEg8RgTh9vNjPlQmOO9xe7GZkdJD69H A40VDdQz3fULETuzy2wywM9O4AQP6qCoAYO/n5olcCDtxE73bProfPKxvgBAtytat/fU jF4w== X-Gm-Message-State: AC+VfDyEKNf8VPUKbSjzMloNw2c+9Gtwj75bUi/XMQQN0z0BASBRRHfY hOtxa6Mcq+tWVAL/QNznnFNjuVG+nBWnlB5bB0Q= X-Google-Smtp-Source: ACHHUZ5yqRtckETnTzYUONA07JhfziOOfU3jJWFy3co4fXK700ThccU0nC+rwsyKBVV8qf5QfwXrXw== X-Received: by 2002:a92:2809:0:b0:33b:c914:a771 with SMTP id l9-20020a922809000000b0033bc914a771mr5286081ilf.6.1685636672493; Thu, 01 Jun 2023 09:24:32 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:32 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass , Anatolij Gustschin Subject: [PATCH 08/40] video: Drop #ifdefs from console_truetype Date: Thu, 1 Jun 2023 10:22:32 -0600 Message-ID: <20230601162404.220488-7-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Use if() instead to reduce the number of build paths. Signed-off-by: Simon Glass --- drivers/video/console_truetype.c | 112 +++++++++++++++---------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c index 6b5390136a7a..0ea8a9f6215e 100644 --- a/drivers/video/console_truetype.c +++ b/drivers/video/console_truetype.c @@ -154,33 +154,33 @@ static int console_truetype_set_row(struct udevice *dev, uint row, int clr) end = line + met->font_size * vid_priv->line_length; switch (vid_priv->bpix) { -#ifdef CONFIG_VIDEO_BPP8 case VIDEO_BPP8: { u8 *dst; - for (dst = line; dst < (u8 *)end; ++dst) - *dst = clr; + if (IS_ENABLED(CONFIG_VIDEO_BPP8)) { + for (dst = line; dst < (u8 *)end; ++dst) + *dst = clr; + } break; } -#endif -#ifdef CONFIG_VIDEO_BPP16 case VIDEO_BPP16: { u16 *dst = line; - for (dst = line; dst < (u16 *)end; ++dst) - *dst = clr; + if (IS_ENABLED(CONFIG_VIDEO_BPP16)) { + for (dst = line; dst < (u16 *)end; ++dst) + *dst = clr; + } break; } -#endif -#ifdef CONFIG_VIDEO_BPP32 case VIDEO_BPP32: { u32 *dst = line; - for (dst = line; dst < (u32 *)end; ++dst) - *dst = clr; + if (IS_ENABLED(CONFIG_VIDEO_BPP32)) { + for (dst = line; dst < (u32 *)end; ++dst) + *dst = clr; + } break; } -#endif default: return -ENOSYS; } @@ -317,52 +317,52 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y, end = dst; } break; -#ifdef CONFIG_VIDEO_BPP16 case VIDEO_BPP16: { uint16_t *dst = (uint16_t *)line + xoff; int i; - for (i = 0; i < width; i++) { - int val = *bits; - int out; - - if (vid_priv->colour_bg) - val = 255 - val; - out = val >> 3 | - (val >> 2) << 5 | - (val >> 3) << 11; - if (vid_priv->colour_fg) - *dst++ |= out; - else - *dst++ &= out; - bits++; + if (IS_ENABLED(CONFIG_VIDEO_BPP16)) { + for (i = 0; i < width; i++) { + int val = *bits; + int out; + + if (vid_priv->colour_bg) + val = 255 - val; + out = val >> 3 | + (val >> 2) << 5 | + (val >> 3) << 11; + if (vid_priv->colour_fg) + *dst++ |= out; + else + *dst++ &= out; + bits++; + } + end = dst; } - end = dst; break; } -#endif -#ifdef CONFIG_VIDEO_BPP32 case VIDEO_BPP32: { u32 *dst = (u32 *)line + xoff; int i; - for (i = 0; i < width; i++) { - int val = *bits; - int out; - - if (vid_priv->colour_bg) - val = 255 - val; - out = val | val << 8 | val << 16; - if (vid_priv->colour_fg) - *dst++ |= out; - else - *dst++ &= out; - bits++; + if (IS_ENABLED(CONFIG_VIDEO_BPP32)) { + for (i = 0; i < width; i++) { + int val = *bits; + int out; + + if (vid_priv->colour_bg) + val = 255 - val; + out = val | val << 8 | val << 16; + if (vid_priv->colour_fg) + *dst++ |= out; + else + *dst++ &= out; + bits++; + } + end = dst; } - end = dst; break; } -#endif default: free(data); return -ENOSYS; @@ -405,33 +405,33 @@ static int console_truetype_erase(struct udevice *dev, int xstart, int ystart, line = start; for (row = ystart; row < yend; row++) { switch (vid_priv->bpix) { -#ifdef CONFIG_VIDEO_BPP8 case VIDEO_BPP8: { uint8_t *dst = line; - for (i = 0; i < pixels; i++) - *dst++ = clr; + if (IS_ENABLED(CONFIG_VIDEO_BPP8)) { + for (i = 0; i < pixels; i++) + *dst++ = clr; + } break; } -#endif -#ifdef CONFIG_VIDEO_BPP16 case VIDEO_BPP16: { uint16_t *dst = line; - for (i = 0; i < pixels; i++) - *dst++ = clr; + if (IS_ENABLED(CONFIG_VIDEO_BPP16)) { + for (i = 0; i < pixels; i++) + *dst++ = clr; + } break; } -#endif -#ifdef CONFIG_VIDEO_BPP32 case VIDEO_BPP32: { uint32_t *dst = line; - for (i = 0; i < pixels; i++) - *dst++ = clr; + if (IS_ENABLED(CONFIG_VIDEO_BPP32)) { + for (i = 0; i < pixels; i++) + *dst++ = clr; + } break; } -#endif default: return -ENOSYS; } From patchwork Thu Jun 1 16:22:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789222 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=KmIyXqLa; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBNS0hyHz20Py for ; Fri, 2 Jun 2023 02:26:48 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id DB59C86346; Thu, 1 Jun 2023 18:24:57 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="KmIyXqLa"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 2DFB68636C; Thu, 1 Jun 2023 18:24:41 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x136.google.com (mail-il1-x136.google.com [IPv6:2607:f8b0:4864:20::136]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id CEF4886345 for ; Thu, 1 Jun 2023 18:24:34 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x136.google.com with SMTP id e9e14a558f8ab-33b9a56e261so4026545ab.0 for ; Thu, 01 Jun 2023 09:24:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636673; x=1688228673; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=U8ZQ64Z7qENNEWUTvYkW05Z6192xhB6jo4sGkKR4twA=; b=KmIyXqLaOYDGvg3j1SeFwIsC1Vk02fLFPYOqhq56/ddGbpCbDUQYJIQuM+KlTNtU7/ Jz+dOMUFC7koqXeMB1Ix4yH3S4CELUSGpKBKTApSIXIf60deNrENtIEdMlGZjRGE1BhE K4OO2w3MAnPjTrF29ZNMgIKsofnq4+69Wn3qA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636673; x=1688228673; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=U8ZQ64Z7qENNEWUTvYkW05Z6192xhB6jo4sGkKR4twA=; b=cqstvDbmeooZUbNU8H5w87WNusP5oiaOddbzhUtvUm+FhEA6mNqSx2lUgJYW1i+6Vr I9pPVBWR/8VqPZ17nOdBSMZ6wJP76zbwdqIOMDHdOs5UVBrmDMJQdL/YM0I54TxWY4wS HulWAk5hv87ncCR/bhyvyRaQ4jU07KCzKLBYAKD8B0+FYGu3oXZRD5Gu2ZmhNSAVsTD0 7UkWCXQca55Ha5xYILu9KoSF/OEdeRdWNWqW2vf4B4z/ZkCsh+mfy7EqN7XsbfJlzPxS q46XQpps14Wx7AYA9cGzDcf9k72IYO2tssYA7DEAEI8melcMQue3nV+1ggyfMuVCKVai wYsg== X-Gm-Message-State: AC+VfDwtupw0JqVr/IHJ3QY5C5eK+MKTVPmwd0dh0BaJSeLe36D8lpnQ aPX5U11xMF1K8kFpePSiyjv2+CAAo6SfAywH/bw= X-Google-Smtp-Source: ACHHUZ6XHPxJx4J1fuEHHUNUtlYpZNWlwpaZYUrEXJ8SRUR8sqe7RVadSQs16aYaIixU8afDDJR09g== X-Received: by 2002:a05:6e02:6d0:b0:33a:56d6:d9a9 with SMTP id p16-20020a056e0206d000b0033a56d6d9a9mr6559292ils.19.1685636673403; Thu, 01 Jun 2023 09:24:33 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:33 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass , Anatolij Gustschin Subject: [PATCH 09/40] video: Provide a way to clear part of the console Date: Thu, 1 Jun 2023 10:22:33 -0600 Message-ID: <20230601162404.220488-8-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean This is useful when the background colour must be written before text is updated, to avoid strange display artifacts. Add a function for this, using the existing code from the truetype console. Signed-off-by: Simon Glass --- drivers/video/console_truetype.c | 72 ++------------------------------ drivers/video/video-uclass.c | 52 +++++++++++++++++++++++ include/video.h | 16 +++++++ 3 files changed, 71 insertions(+), 69 deletions(-) diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c index 0ea8a9f6215e..63d7557c71a0 100644 --- a/drivers/video/console_truetype.c +++ b/drivers/video/console_truetype.c @@ -378,72 +378,6 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y, return width_frac; } -/** - * console_truetype_erase() - Erase a character - * - * This is used for backspace. We erase a square of the display within the - * given bounds. - * - * @dev: Device to update - * @xstart: X start position in pixels from the left - * @ystart: Y start position in pixels from the top - * @xend: X end position in pixels from the left - * @yend: Y end position in pixels from the top - * @clr: Value to write - * Return: 0 if OK, -ENOSYS if the display depth is not supported - */ -static int console_truetype_erase(struct udevice *dev, int xstart, int ystart, - int xend, int yend, int clr) -{ - struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); - void *start, *line; - int pixels = xend - xstart; - int row, i, ret; - - start = vid_priv->fb + ystart * vid_priv->line_length; - start += xstart * VNBYTES(vid_priv->bpix); - line = start; - for (row = ystart; row < yend; row++) { - switch (vid_priv->bpix) { - case VIDEO_BPP8: { - uint8_t *dst = line; - - if (IS_ENABLED(CONFIG_VIDEO_BPP8)) { - for (i = 0; i < pixels; i++) - *dst++ = clr; - } - break; - } - case VIDEO_BPP16: { - uint16_t *dst = line; - - if (IS_ENABLED(CONFIG_VIDEO_BPP16)) { - for (i = 0; i < pixels; i++) - *dst++ = clr; - } - break; - } - case VIDEO_BPP32: { - uint32_t *dst = line; - - if (IS_ENABLED(CONFIG_VIDEO_BPP32)) { - for (i = 0; i < pixels; i++) - *dst++ = clr; - } - break; - } - default: - return -ENOSYS; - } - line += vid_priv->line_length; - } - ret = vidconsole_sync_copy(dev, start, line); - if (ret) - return ret; - - return 0; -} - /** * console_truetype_backspace() - Handle a backspace operation * @@ -482,9 +416,9 @@ static int console_truetype_backspace(struct udevice *dev) else xend = vid_priv->xsize; - console_truetype_erase(dev, VID_TO_PIXEL(pos->xpos_frac), pos->ypos, - xend, pos->ypos + vc_priv->y_charsize, - vid_priv->colour_bg); + video_fill_part(vid_dev, VID_TO_PIXEL(pos->xpos_frac), pos->ypos, + xend, pos->ypos + vc_priv->y_charsize, + vid_priv->colour_bg); /* Move the cursor back to where it was when we pushed this record */ vc_priv->xcur_frac = pos->xpos_frac; diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index 8396bdfb11e1..1db049bec004 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -142,6 +142,58 @@ int video_reserve(ulong *addrp) return 0; } +int video_fill_part(struct udevice *dev, int xstart, int ystart, int xend, + int yend, u32 colour) +{ + struct video_priv *priv = dev_get_uclass_priv(dev); + void *start, *line; + int pixels = xend - xstart; + int row, i, ret; + + start = priv->fb + ystart * priv->line_length; + start += xstart * VNBYTES(priv->bpix); + line = start; + for (row = ystart; row < yend; row++) { + switch (priv->bpix) { + case VIDEO_BPP8: { + u8 *dst = line; + + if (IS_ENABLED(CONFIG_VIDEO_BPP8)) { + for (i = 0; i < pixels; i++) + *dst++ = colour; + } + break; + } + case VIDEO_BPP16: { + u16 *dst = line; + + if (IS_ENABLED(CONFIG_VIDEO_BPP16)) { + for (i = 0; i < pixels; i++) + *dst++ = colour; + } + break; + } + case VIDEO_BPP32: { + u32 *dst = line; + + if (IS_ENABLED(CONFIG_VIDEO_BPP32)) { + for (i = 0; i < pixels; i++) + *dst++ = colour; + } + break; + } + default: + return -ENOSYS; + } + line += priv->line_length; + } + ret = video_sync_copy(dev, start, line); + if (ret) + return ret; + + return 0; +} + int video_fill(struct udevice *dev, u32 colour) { struct video_priv *priv = dev_get_uclass_priv(dev); diff --git a/include/video.h b/include/video.h index 29c4f51efb08..e5b0db294734 100644 --- a/include/video.h +++ b/include/video.h @@ -203,6 +203,22 @@ int video_clear(struct udevice *dev); */ int video_fill(struct udevice *dev, u32 colour); +/** + * video_fill_part() - Erase a region + * + * Erase a rectangle of the display within the given bounds. + * + * @dev: Device to update + * @xstart: X start position in pixels from the left + * @ystart: Y start position in pixels from the top + * @xend: X end position in pixels from the left + * @yend: Y end position in pixels from the top + * @colour: Value to write + * Return: 0 if OK, -ENOSYS if the display depth is not supported + */ +int video_fill_part(struct udevice *dev, int xstart, int ystart, int xend, + int yend, u32 colour); + /** * video_sync() - Sync a device's frame buffer with its hardware * From patchwork Thu Jun 1 16:22:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789220 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=T0Jd9x6o; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBN84Df6z20Py for ; Fri, 2 Jun 2023 02:26:32 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id B55A986378; Thu, 1 Jun 2023 18:24:54 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="T0Jd9x6o"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id BB23986343; Thu, 1 Jun 2023 18:24:40 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-io1-xd2b.google.com (mail-io1-xd2b.google.com [IPv6:2607:f8b0:4864:20::d2b]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id B16228633F for ; Thu, 1 Jun 2023 18:24:35 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd2b.google.com with SMTP id ca18e2360f4ac-7770b7c2fa5so2750639f.0 for ; Thu, 01 Jun 2023 09:24:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636674; x=1688228674; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=zCUR+PvwLwWHCGdnY2VqNaxxgHBFRHx4ga1pYR3veNg=; b=T0Jd9x6oz900Zv80Du5PUYqC3+rsTCe4Gb9V24J4fSTOZ2d82s6+mI8QiA6JylRofJ +cW0CdCiNmThWBR+MJ6kNT+2oFoz9DFb7UU50GscXTg0lhfsX4m1txbhnrn0aJ97nsQF wqR6zZuAOGT2i5dD4GJqREGe8F2q+0THTAO1Q= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636674; x=1688228674; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=zCUR+PvwLwWHCGdnY2VqNaxxgHBFRHx4ga1pYR3veNg=; b=WFxvAMioU7kISuwHg8BupMJ7ZMzputK/xMJO56W3XHjvTe/jPhRx8ROTTfVJyw/V8m v61ddsNFW8Hj6CigNJ+FYdkdUnchxKXBLBdf7Aqf5563UC1pGK7gsRrBadhuAgnygOpT i+CMPVaCyX/hRjqQ000vnt8+m4ESbKzz4arzWfCpuNIrFLUpULXb/3QqBz+dYehviAaW Qc9qpgh7ViDIEz0YD7ixoRSf906ATyubWDGs14gY1kpT0yXcOMoH4ClWOOCwITzpBRfg 1jl+adBXE3qmdlpSPHOPcCRGgSD2NFbGO/NGIgIwCVSDq0t6Ffl6cjjvyFNkCYsfqZ0A q0vg== X-Gm-Message-State: AC+VfDyKxSijgn80VyEEneT0VAJpBacdiJxsYtZYcD18/HCyfOn4UUhp cdctD2VZWH+YZLiEChcFdhsWGxY68rPFk1xaLNo= X-Google-Smtp-Source: ACHHUZ5+1VRdnBWtYP8noeRWZLS2YmmYVAiNTcR6Wz6TS5oRcWlTEvE3GUPpEwBZZdwV9CyHyUQKFg== X-Received: by 2002:a92:d352:0:b0:331:5d7c:776d with SMTP id a18-20020a92d352000000b003315d7c776dmr6547322ilh.17.1685636674267; Thu, 01 Jun 2023 09:24:34 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:34 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 10/40] expo: Store the console in the expo Date: Thu, 1 Jun 2023 10:22:34 -0600 Message-ID: <20230601162404.220488-9-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Rather than finding this each time, keep a pointer to it. This simplifies the code a little. Signed-off-by: Simon Glass --- boot/expo.c | 9 +++++++++ boot/scene.c | 10 ++-------- include/expo.h | 2 ++ 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/boot/expo.c b/boot/expo.c index 05950a176038..cd1b1a3de50c 100644 --- a/boot/expo.c +++ b/boot/expo.c @@ -83,7 +83,16 @@ const char *expo_get_str(struct expo *exp, uint id) int expo_set_display(struct expo *exp, struct udevice *dev) { + struct udevice *cons; + int ret; + + ret = device_find_first_child_by_uclass(dev, UCLASS_VIDEO_CONSOLE, + &cons); + if (ret) + return log_msg_ret("con", ret); + exp->display = dev; + exp->cons = cons; return 0; } diff --git a/boot/scene.c b/boot/scene.c index d2f77c008cf7..7e9ba047f2d4 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -278,16 +278,10 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode) { struct scene *scn = obj->scene; struct expo *exp = scn->expo; - struct udevice *cons, *dev = exp->display; + struct udevice *dev = exp->display; + struct udevice *cons = text_mode ? NULL : exp->cons; int x, y, ret; - cons = NULL; - if (!text_mode) { - ret = device_find_first_child_by_uclass(dev, - UCLASS_VIDEO_CONSOLE, - &cons); - } - x = obj->x; y = obj->y; diff --git a/include/expo.h b/include/expo.h index 8827f4b0b45f..06f5629e03f8 100644 --- a/include/expo.h +++ b/include/expo.h @@ -50,6 +50,7 @@ struct expo_action { * * @name: Name of the expo (allocated) * @display: Display to use (`UCLASS_VIDEO`), or NULL to use text mode + * @cons: Console to use (`UCLASS_VIDEO_CONSOLE`), or NULL to use text mode * @scene_id: Current scene ID (0 if none) * @next_id: Next ID number to use, for automatic allocation * @action: Action selected by user. At present only one is supported, with the @@ -62,6 +63,7 @@ struct expo_action { struct expo { char *name; struct udevice *display; + struct udevice *cons; uint scene_id; uint next_id; struct expo_action action; From patchwork Thu Jun 1 16:22:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789224 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=NakV0eFd; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBNy00Jdz20Py for ; Fri, 2 Jun 2023 02:27:13 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 6000986389; Thu, 1 Jun 2023 18:25:10 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="NakV0eFd"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 77EFA86345; Thu, 1 Jun 2023 18:24:42 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-io1-xd2e.google.com (mail-io1-xd2e.google.com [IPv6:2607:f8b0:4864:20::d2e]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 119AB8634E for ; Thu, 1 Jun 2023 18:24:37 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd2e.google.com with SMTP id ca18e2360f4ac-777094e3d7bso2266839f.1 for ; Thu, 01 Jun 2023 09:24:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636675; x=1688228675; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=aJbcp783FHp3bjCFsi4mpGbNBo3e2JVxVJvzkauLzBY=; b=NakV0eFdqxe9YbBmFBAP1QyWU0liG/STX15YsGoqLa7IZtE/xIdciqRLS01fYkRryp VLoRAzR9AoZx9TQGSNel3neu0lpVE0lf//rMX5laTgekRkWTz6+Z44pJ27+lTUGcQMSd qT7uMJwDnhTvf+tsM6cKLTVjvoBOteE4LPZ+M= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636675; x=1688228675; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=aJbcp783FHp3bjCFsi4mpGbNBo3e2JVxVJvzkauLzBY=; b=W0SkjFDPCXJhVLYWujvJUueWeqI9ZG0m+oiMMFwAZG+h21E3Q4Y75I719pVAr+WaOe udFrrqlfvU6w3OxWG68o2zQgk2TnaJ6KxN0RiaDLfXu1OfG7lPrDNP2PnUOjQ8guwZix gGXWL/S0Aya+H0lxk2XRtglIEnCHza6oTzhC7gqw+dQh7kCcFMx4wGFQTNYfeX4FmarB bcjwNLACpxxh3BKfykloQqAZRP2dRGOODf3ndo9+OU7AabWdEQhb5auFXuQESgwhrih8 4Ukv4rfbnEFUbRqT39NcW2nvM0UQBMDjDN5dD+xGPZgUwf9CskOWRK+hKO0dla7Xs7QL r6kQ== X-Gm-Message-State: AC+VfDyiQGMLdcZAsKFLCU39eK0oXJAtWEAcbbcaAMweVejj1Q7o9DbW QoKqxS1wKNoFOVUj+Lzd432NWraF/iAKhx/lk88= X-Google-Smtp-Source: ACHHUZ62YbWXWp/3IIVODRmE2eo9pC8wqaDzRLyWnt8ZSZ3Ykm0XNayv3nfMBXI7/IHKw65oi7j5Ng== X-Received: by 2002:a92:dc48:0:b0:33b:4518:855b with SMTP id x8-20020a92dc48000000b0033b4518855bmr4571205ilq.31.1685636675088; Thu, 01 Jun 2023 09:24:35 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:34 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 11/40] expo: Avoid automatically arranging the scene Date: Thu, 1 Jun 2023 10:22:35 -0600 Message-ID: <20230601162404.220488-10-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean This should ideally be done once after all scene changes have been made. Require an explicit call when everything is ready. Always arrange after a key it sent, just for convenience. Signed-off-by: Simon Glass --- boot/bootflow_menu.c | 4 ++++ boot/expo.c | 15 ++++++++++++++- boot/scene.c | 7 ------- boot/scene_menu.c | 9 --------- test/boot/expo.c | 4 +++- 5 files changed, 21 insertions(+), 18 deletions(-) diff --git a/boot/bootflow_menu.c b/boot/bootflow_menu.c index 7f06dac0af77..de0f44535690 100644 --- a/boot/bootflow_menu.c +++ b/boot/bootflow_menu.c @@ -124,6 +124,10 @@ int bootflow_menu_new(struct expo **expp) priv->num_bootflows++; } + ret = scene_arrange(scn); + if (ret) + return log_msg_ret("arr", ret); + *expp = exp; return 0; diff --git a/boot/expo.c b/boot/expo.c index cd1b1a3de50c..bfdda9570c60 100644 --- a/boot/expo.c +++ b/boot/expo.c @@ -116,8 +116,16 @@ struct scene *expo_lookup_scene_id(struct expo *exp, uint scene_id) int expo_set_scene_id(struct expo *exp, uint scene_id) { - if (!expo_lookup_scene_id(exp, scene_id)) + struct scene *scn; + int ret; + + scn = expo_lookup_scene_id(exp, scene_id); + if (!scn) return log_msg_ret("id", -ENOENT); + ret = scene_arrange(scn); + if (ret) + return log_msg_ret("arr", ret); + exp->scene_id = scene_id; return 0; @@ -165,6 +173,11 @@ int expo_send_key(struct expo *exp, int key) ret = scene_send_key(scn, key, &exp->action); if (ret) return log_msg_ret("key", ret); + + /* arrange it to get any changes */ + ret = scene_arrange(scn); + if (ret) + return log_msg_ret("arr", ret); } return scn ? 0 : -ECHILD; diff --git a/boot/scene.c b/boot/scene.c index 7e9ba047f2d4..1383be20321f 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -211,8 +211,6 @@ int scene_obj_set_pos(struct scene *scn, uint id, int x, int y) return log_msg_ret("find", -ENOENT); obj->x = x; obj->y = y; - if (obj->type == SCENEOBJT_MENU) - scene_menu_arrange(scn, (struct scene_obj_menu *)obj); return 0; } @@ -391,11 +389,6 @@ int scene_send_key(struct scene *scn, int key, struct expo_action *event) ret = scene_menu_send_key(scn, menu, key, event); if (ret) return log_msg_ret("key", ret); - - /* only allow one menu */ - ret = scene_menu_arrange(scn, menu); - if (ret) - return log_msg_ret("arr", ret); break; } } diff --git a/boot/scene_menu.c b/boot/scene_menu.c index 18998e862ab3..9ee911f2fa38 100644 --- a/boot/scene_menu.c +++ b/boot/scene_menu.c @@ -158,10 +158,6 @@ int scene_menu(struct scene *scn, const char *name, uint id, *menup = menu; INIT_LIST_HEAD(&menu->item_head); - ret = scene_menu_arrange(scn, menu); - if (ret) - return log_msg_ret("pos", ret); - return menu->obj.id; } @@ -258,7 +254,6 @@ int scene_menuitem(struct scene *scn, uint menu_id, const char *name, uint id, { struct scene_obj_menu *menu; struct scene_menitem *item; - int ret; menu = scene_obj_find(scn, menu_id, SCENEOBJT_MENU); if (!menu) @@ -285,10 +280,6 @@ int scene_menuitem(struct scene *scn, uint menu_id, const char *name, uint id, item->flags = flags; list_add_tail(&item->sibling, &menu->item_head); - ret = scene_menu_arrange(scn, menu); - if (ret) - return log_msg_ret("pos", ret); - if (itemp) *itemp = item; diff --git a/test/boot/expo.c b/test/boot/expo.c index 3c0bc78bb7a4..56a22ba9b066 100644 --- a/test/boot/expo.c +++ b/test/boot/expo.c @@ -348,7 +348,9 @@ static int expo_object_menu(struct unit_test_state *uts) ut_asserteq(desc_id, item->desc_id); ut_asserteq(preview_id, item->preview_id); - /* adding an item should cause the first item to become current */ + ut_assertok(scene_arrange(scn)); + + /* arranging the scene should cause the first item to become current */ ut_asserteq(id, menu->cur_item_id); /* the title should be at the top */ From patchwork Thu Jun 1 16:22:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789223 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=kvmtp8eH; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBNj1tlDz20Py for ; Fri, 2 Jun 2023 02:27:01 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 1B6ED86384; Thu, 1 Jun 2023 18:25:05 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="kvmtp8eH"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 1060D8632B; Thu, 1 Jun 2023 18:24:43 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x131.google.com (mail-il1-x131.google.com [IPv6:2607:f8b0:4864:20::131]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 7F0E386347 for ; Thu, 1 Jun 2023 18:24:38 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x131.google.com with SMTP id e9e14a558f8ab-33b1e83e1daso3968725ab.0 for ; Thu, 01 Jun 2023 09:24:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636676; x=1688228676; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=AyiNZVQweQM7zPkbsabyNjQoMkC4CenwapEAv3PlUvk=; b=kvmtp8eHIktwTbAcleajq/IShShRx2gwzu+fRfP045gbSTQL7RGXamcVm3Rr51pkTB vrpYSQvaeL7p+sH6mW/JS6X129T3of4HcVvURLZ6h2r4CeSH+Is2CVFyJG5pMVoQsz4W MAXx4j6zh3Mb9xC/tLpToXqVp+DDsaIKmADvI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636676; x=1688228676; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=AyiNZVQweQM7zPkbsabyNjQoMkC4CenwapEAv3PlUvk=; b=GzTIww7vHfrlljjr69R3Og7HxY5udOafgTcXPjT1daosKUjYUBhKfoxxB3gLBpwJjo eZQRVb42qTA9asX4AqIVHWWy3V/yqutPUu97P7fcAMuimA6Ii8EtFIey4FOAqIYTd3mA S4dvepRxWsmo+6x78rugemNsb0tVTnS3KYiOwbDjz6rUND/PyXBSRA5I395sGvTarCTU 8mAlkLf0tanDAO9OXkvW6BuxYqQzwwW5hMkFIsi54eMeOhJgSjfkpdUXHPuNZgCKlGnZ CQxAK4Ha7ZhKuZ9d6vH/sR4RCQEDO39BvuYq598JfVzjoAaENFWHp9gYh4yVvZI1cDT4 Ukow== X-Gm-Message-State: AC+VfDx2O46CfRi1cBPK6wvNntIR+xABnd6M7fETtuiMIipPtp+ASLcN ulmdzHGEUr+XnXEEpd3r0KuqbKgUfYgTmz8MmGQ= X-Google-Smtp-Source: ACHHUZ4gV1T7aQ7HbKe0Wwx06AOyq9UxOPI2T6bjLrX5y72Gvw3LdqozIIaNnEmt6WsY3qRxDN6gWA== X-Received: by 2002:a92:dc4b:0:b0:32a:b644:af65 with SMTP id x11-20020a92dc4b000000b0032ab644af65mr5504742ilq.7.1685636676214; Thu, 01 Jun 2023 09:24:36 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:35 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 12/40] console: Correct truetype spacing error Date: Thu, 1 Jun 2023 10:22:36 -0600 Message-ID: <20230601162404.220488-11-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean The putc_xy() method is supposed to return the amount of space used. The existing implementation erroneously adds the previous sub-pixel position to the returned value. This spaces out the characters very slightly more than it should. It is seldom noticeable but it does make accurate measurement of the text impossible. Fix this minor but long-standing bug. Fixes: a29b012037c ("video: Add a console driver that uses TrueType fonts") Signed-off-by: Simon Glass --- drivers/video/console_truetype.c | 2 +- test/dm/video.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c index 63d7557c71a0..6f3fc82f9b05 100644 --- a/drivers/video/console_truetype.c +++ b/drivers/video/console_truetype.c @@ -256,7 +256,7 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y, */ x_shift = xpos - (double)tt_floor(xpos); xpos += advance * met->scale; - width_frac = (int)VID_TO_POS(xpos); + width_frac = (int)VID_TO_POS(advance * met->scale); if (x + width_frac >= vc_priv->xsize_frac) return -EAGAIN; diff --git a/test/dm/video.c b/test/dm/video.c index 30778157d940..6d9c55c14035 100644 --- a/test/dm/video.c +++ b/test/dm/video.c @@ -556,7 +556,7 @@ static int dm_test_video_truetype(struct unit_test_state *uts) ut_assertok(video_get_nologo(uts, &dev)); ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); vidconsole_put_string(con, test_string); - ut_asserteq(12237, compress_frame_buffer(uts, dev)); + ut_asserteq(12187, compress_frame_buffer(uts, dev)); return 0; } @@ -577,7 +577,7 @@ static int dm_test_video_truetype_scroll(struct unit_test_state *uts) ut_assertok(video_get_nologo(uts, &dev)); ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); vidconsole_put_string(con, test_string); - ut_asserteq(35030, compress_frame_buffer(uts, dev)); + ut_asserteq(34481, compress_frame_buffer(uts, dev)); return 0; } @@ -598,7 +598,7 @@ static int dm_test_video_truetype_bs(struct unit_test_state *uts) ut_assertok(video_get_nologo(uts, &dev)); ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); vidconsole_put_string(con, test_string); - ut_asserteq(29018, compress_frame_buffer(uts, dev)); + ut_asserteq(29579, compress_frame_buffer(uts, dev)); return 0; } From patchwork Thu Jun 1 16:22:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789231 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=jrORPJ2I; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBPQ73GRz20Py for ; Fri, 2 Jun 2023 02:27:38 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 681A5863A4; Thu, 1 Jun 2023 18:25:17 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="jrORPJ2I"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 4EE298636C; Thu, 1 Jun 2023 18:24:44 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x12e.google.com (mail-il1-x12e.google.com [IPv6:2607:f8b0:4864:20::12e]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 055F786339 for ; Thu, 1 Jun 2023 18:24:40 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x12e.google.com with SMTP id e9e14a558f8ab-33bbc91dcb7so4221335ab.3 for ; Thu, 01 Jun 2023 09:24:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636677; x=1688228677; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=llOjgta2aD/fs0Gu5lvcJMuUXy3p15YrZiES9CqlLRs=; b=jrORPJ2IhMxzgycL73h2DeLA3tVfmtxH8dH6FQy/jHVmqkNKSCOz44rSe2Of5vLxdB 7K4Q3sVF+7ET5T7FZi1PpK/gd9JX1bTsanpbFFmnQBBQAILexTXBzySaUAfGZmKj5GAs 1QCq3ho/ufwWhYfOHSdSwJh7M5HDBkfzHm7GU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636677; x=1688228677; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=llOjgta2aD/fs0Gu5lvcJMuUXy3p15YrZiES9CqlLRs=; b=lf3tgUGMqJwtzy6K0MfXawjOJ2+MykyDxyfhaQA4dPePxguUdUoZ8DpNSr4BJVm5xn J4SbWO+Q95zAzYwUapE2Tl/ucwvN0V98UYPa6yuWZZ1IFwOKu/pjhb6JnoOhQtf1Ju9s 05e14lGPRhqG0VhAZtR8rc3YOdRzdqbzxq7Kf2uKyqwr5xQBNMMjoxJgxZ9doqhYUEkO YUvuPxS3LPvHOLbhvxGN/wuIkfMbjvut31wHBSpG7mrRJKFJIrxxKNDCMHKfK+0WMKKn Nv3NFK/ksNWo3uESFWdtoL9CX2AnwMzLCDXbmwAdIaD5gSKHMG4XqL6s/3E5EbeeQH/s gzKQ== X-Gm-Message-State: AC+VfDz0AM+qxbNeDLAsBEDnknItViZKYyjsx9h/nL2/sbs78Lsy1odU 80zmvDMa3f3oAnnVTAlwnAs5jnmF2ufGI8jJBAc= X-Google-Smtp-Source: ACHHUZ4gMpncesadTo5oU0ues920/aCsTONQMud6PMkrv03fVU6ep9YDNgtk4r4Qkq7LpNSSZCKU7w== X-Received: by 2002:a92:d791:0:b0:338:d170:6e32 with SMTP id d17-20020a92d791000000b00338d1706e32mr7236615iln.7.1685636677239; Thu, 01 Jun 2023 09:24:37 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:36 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 13/40] expo: Rename exp_set_text_mode() Date: Thu, 1 Jun 2023 10:22:37 -0600 Message-ID: <20230601162404.220488-12-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Rename this function to match its peers, using the full "expo' prefix. Signed-off-by: Simon Glass --- boot/bootflow_menu.c | 2 +- boot/expo.c | 2 +- include/expo.h | 4 ++-- test/boot/expo.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/boot/bootflow_menu.c b/boot/bootflow_menu.c index de0f44535690..7c1abe5772cd 100644 --- a/boot/bootflow_menu.c +++ b/boot/bootflow_menu.c @@ -209,7 +209,7 @@ int bootflow_menu_run(struct bootstd_priv *std, bool text_mode, return log_msg_ret("scn", ret); if (text_mode) - exp_set_text_mode(exp, text_mode); + expo_set_text_mode(exp, text_mode); done = false; do { diff --git a/boot/expo.c b/boot/expo.c index bfdda9570c60..e7c81a3983d3 100644 --- a/boot/expo.c +++ b/boot/expo.c @@ -97,7 +97,7 @@ int expo_set_display(struct expo *exp, struct udevice *dev) return 0; } -void exp_set_text_mode(struct expo *exp, bool text_mode) +void expo_set_text_mode(struct expo *exp, bool text_mode) { exp->text_mode = text_mode; } diff --git a/include/expo.h b/include/expo.h index 06f5629e03f8..f77ee7085192 100644 --- a/include/expo.h +++ b/include/expo.h @@ -306,12 +306,12 @@ int expo_set_scene_id(struct expo *exp, uint scene_id); int expo_render(struct expo *exp); /** - * exp_set_text_mode() - Controls whether the expo renders in text mode + * expo_set_text_mode() - Controls whether the expo renders in text mode * * @exp: Expo to update * @text_mode: true to use text mode, false to use the console */ -void exp_set_text_mode(struct expo *exp, bool text_mode); +void expo_set_text_mode(struct expo *exp, bool text_mode); /** * scene_new() - create a new scene in a expo diff --git a/test/boot/expo.c b/test/boot/expo.c index 56a22ba9b066..70750d307ffa 100644 --- a/test/boot/expo.c +++ b/test/boot/expo.c @@ -507,7 +507,7 @@ static int expo_render_image(struct unit_test_state *uts) ut_assert_console_end(); /* now try in text mode */ - exp_set_text_mode(exp, true); + expo_set_text_mode(exp, true); ut_assertok(expo_render(exp)); ut_assert_nextline("U-Boot : Boot Menu"); From patchwork Thu Jun 1 16:22:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789234 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=RixzUV/d; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBQH3mKnz20Py for ; Fri, 2 Jun 2023 02:28:23 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 5039E863BA; Thu, 1 Jun 2023 18:25:26 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="RixzUV/d"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 6AFA886377; Thu, 1 Jun 2023 18:24:51 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x136.google.com (mail-il1-x136.google.com [IPv6:2607:f8b0:4864:20::136]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id C74A886362 for ; Thu, 1 Jun 2023 18:24:38 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x136.google.com with SMTP id e9e14a558f8ab-33b9a56e261so4026945ab.0 for ; Thu, 01 Jun 2023 09:24:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636678; x=1688228678; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=0v/mo6L4Hih1dVg7DECQg1b0GPEkULCbv7CbQiRYvhU=; b=RixzUV/drokcLz3vjhr9Rc5AZnqAjneShm0f9ip0OYxfw+6/omdXR40vsJYm+5JAvL Kt398VS4mKloAioi20IyAlXQs3Oq0uNV1ZtZhvrcJIEz4iOQxKVRlcFa048wFv0Y2DXL QxyTNzvEPyXrEkC/M2qZ9tRRaN9hgInh2A9eE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636678; x=1688228678; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=0v/mo6L4Hih1dVg7DECQg1b0GPEkULCbv7CbQiRYvhU=; b=AjIvIQnpI9ydFcqCUkgQYoiuBPU9vLKhKRbIg7pZ87jG0T6LpCW1fBZ0uZEoxzv+Pt 2BHQJ8pY9nJtbRfJnIBNDf8biOagEdhnWpSKpKUtFtraiuVfu9NvRtxmdjsI7HqXNBhH f1VcyQK1t7DBzPHtLjm7PUv07r3A8TrwgVGSVbnxZZmnCZJ7Bbr1HfL4Ud12B7upNwAm yhBTCiao6jsFl1sc5d6tSmGrE3PBLRk2ftT7yqBpFUfI5SfbzGY+L7k52Qqc5seeU5kn CJgnKrzhw1lGhdgJlvUbZqTSHxirIjgGmL985wq1Gl5paVBxoC/kRZaHa9OT4jzDlDlV frrA== X-Gm-Message-State: AC+VfDwVYqWVL/de47Mjh7ho/sjz+rxw6ZAK0yek4hu6jLMPjdKxVkZt ZlLo269SaNeYPu7+NE+cb60boK6eRMIEKiRmhpE= X-Google-Smtp-Source: ACHHUZ6JQcuobLOn3FAvUkS90OGdycF/cUUsfoGt6c/CeX0qV6WLaHFrrWjQJT1+lVW0rkTa+gsUcg== X-Received: by 2002:a92:d1c3:0:b0:33b:6f65:2dd0 with SMTP id u3-20020a92d1c3000000b0033b6f652dd0mr6476161ilg.29.1685636678177; Thu, 01 Jun 2023 09:24:38 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:37 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 14/40] fs: Create functions to load and allocate a file Date: Thu, 1 Jun 2023 10:22:38 -0600 Message-ID: <20230601162404.220488-13-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean This functionality current sits in bootstd, but it is more generally useful. Add a function to load a file into memory, allocating it as needed. Adjust bootstd to use this version. Note: Tests are added in the subsequent patch which converts the 'cat' command to use this function. Signed-off-by: Simon Glass --- boot/bootmeth-uclass.c | 30 ++-------------------- fs/fs.c | 58 ++++++++++++++++++++++++++++++++++++++++++ include/fs.h | 38 +++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 28 deletions(-) diff --git a/boot/bootmeth-uclass.c b/boot/bootmeth-uclass.c index 3b3e0614dafa..701ee8ad1c8f 100644 --- a/boot/bootmeth-uclass.c +++ b/boot/bootmeth-uclass.c @@ -301,32 +301,6 @@ int bootmeth_try_file(struct bootflow *bflow, struct blk_desc *desc, return 0; } -static int alloc_file(const char *fname, uint size, void **bufp) -{ - loff_t bytes_read; - ulong addr; - char *buf; - int ret; - - buf = malloc(size + 1); - if (!buf) - return log_msg_ret("buf", -ENOMEM); - addr = map_to_sysmem(buf); - - ret = fs_read(fname, addr, 0, size, &bytes_read); - if (ret) { - free(buf); - return log_msg_ret("read", ret); - } - if (size != bytes_read) - return log_msg_ret("bread", -EIO); - buf[size] = '\0'; - - *bufp = buf; - - return 0; -} - int bootmeth_alloc_file(struct bootflow *bflow, uint size_limit, uint align) { void *buf; @@ -338,7 +312,7 @@ int bootmeth_alloc_file(struct bootflow *bflow, uint size_limit, uint align) if (size > size_limit) return log_msg_ret("chk", -E2BIG); - ret = alloc_file(bflow->fname, bflow->size, &buf); + ret = fs_read_alloc(bflow->fname, bflow->size, align, &buf); if (ret) return log_msg_ret("all", ret); @@ -374,7 +348,7 @@ int bootmeth_alloc_other(struct bootflow *bflow, const char *fname, if (ret) return log_msg_ret("fs", ret); - ret = alloc_file(path, size, &buf); + ret = fs_read_alloc(path, size, 0, &buf); if (ret) return log_msg_ret("all", ret); diff --git a/fs/fs.c b/fs/fs.c index 8324b4a22f20..2b815b1db0fe 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -26,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -1008,3 +1010,59 @@ int do_fs_types(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) puts("\n"); return CMD_RET_SUCCESS; } + +int fs_read_alloc(const char *fname, ulong size, uint align, void **bufp) +{ + loff_t bytes_read; + ulong addr; + char *buf; + int ret; + + buf = memalign(align, size + 1); + if (!buf) + return log_msg_ret("buf", -ENOMEM); + addr = map_to_sysmem(buf); + + ret = fs_read(fname, addr, 0, size, &bytes_read); + if (ret) { + free(buf); + return log_msg_ret("read", ret); + } + if (size != bytes_read) + return log_msg_ret("bread", -EIO); + buf[size] = '\0'; + + *bufp = buf; + + return 0; +} + +int fs_load_alloc(const char *ifname, const char *dev_part_str, + const char *fname, ulong max_size, ulong align, void **bufp, + ulong *sizep) +{ + loff_t size; + void *buf; + int ret; + + if (fs_set_blk_dev(ifname, dev_part_str, FS_TYPE_ANY)) + return log_msg_ret("set", -ENOMEDIUM); + + ret = fs_size(fname, &size); + if (ret) + return log_msg_ret("sz", -ENOENT); + + if (size >= (max_size ?: SZ_1G)) + return log_msg_ret("sz", -E2BIG); + + if (fs_set_blk_dev(ifname, dev_part_str, FS_TYPE_ANY)) + return log_msg_ret("set", -ENOMEDIUM); + + ret = fs_read_alloc(fname, size, align, &buf); + if (ret) + return log_msg_ret("al", ret); + *sizep = size; + *bufp = buf; + + return 0; +} diff --git a/include/fs.h b/include/fs.h index 8370d88cb203..e341a0ed01bf 100644 --- a/include/fs.h +++ b/include/fs.h @@ -300,4 +300,42 @@ int do_fs_type(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); */ int do_fs_types(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); +/** + * fs_read_alloc() - Allocate space for a file and read it + * + * You must call fs_set_blk_dev() or a similar function before calling this, + * since that sets up the block device to use. + * + * The file is terminated with a nul character + * + * @fname: Filename to read + * @size: Size of file to read (must be correct!) + * @align: Alignment to use for memory allocation (0 for default) + * @bufp: On success, returns the allocated buffer with the nul-terminated file + * in it + * Return: 0 if OK, -ENOMEM if out of memory, -EIO if read failed + */ +int fs_read_alloc(const char *fname, ulong size, uint align, void **bufp); + +/** + * fs_load_alloc() - Load a file into allocated space + * + * The file is terminated with a nul character + * + * @ifname: Interface name to read from (e.g. "mmc") + * @dev_part_str: Device and partition string (e.g. "1:2") + * @fname: Filename to read + * @max_size: Maximum allowed size for the file (use 0 for 1GB) + * @align: Alignment to use for memory allocation (0 for default) + * @bufp: On success, returns the allocated buffer with the nul-terminated file + * in it + * @sizep: On success, returns the size of the file + * Return: 0 if OK, -ENOMEM if out of memory, -ENOENT if the file does not + * exist, -ENOMEDIUM if the device does not exist, -E2BIG if the file is too + * large (greater than @max_size), -EIO if read failed + */ +int fs_load_alloc(const char *ifname, const char *dev_part_str, + const char *fname, ulong max_size, ulong align, void **bufp, + ulong *sizep); + #endif /* _FS_H */ From patchwork Thu Jun 1 16:22:39 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789233 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=Rq5pL1T4; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBQ253LGz20Py for ; Fri, 2 Jun 2023 02:28:10 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id D820486393; Thu, 1 Jun 2023 18:25:23 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="Rq5pL1T4"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 3960786345; Thu, 1 Jun 2023 18:24:50 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 Received: from mail-il1-x136.google.com (mail-il1-x136.google.com [IPv6:2607:f8b0:4864:20::136]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 5071586346 for ; Thu, 1 Jun 2023 18:24:42 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x136.google.com with SMTP id e9e14a558f8ab-33b3cfb9495so4010715ab.2 for ; Thu, 01 Jun 2023 09:24:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636679; x=1688228679; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=5QDWyxpNa+KJ6OkJN3Qad8eS1n9L7rsoNvHnEi8rws8=; b=Rq5pL1T4gpMSicRx1JbfO02Ayd8lrJNWlWdGj1dtMQbOvCpV+90W3wPqhdhrnYUPSH 4LC/+vW06yKprMp7+HmSSvCIpjA5MuKLxxFLmllhsZUIljC/sQykiOIVHc/NEnupzMOR 8VSfJLvB1/tCEAmnv8QNlDjBrb8WqprxojZbE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636679; x=1688228679; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=5QDWyxpNa+KJ6OkJN3Qad8eS1n9L7rsoNvHnEi8rws8=; b=aPr6Iz1z8R3jff3M5eObtyRRTF6t0+gzEJV6LT7ZrXcmE+6qbCUecb4j2puYQJWZ7k tr+qCGbV8r83kcaocWFsH5Yit4AIcEkfjsRvvzHwsG5J1rRS39lpLN9UbWZQ9I5QD26V ukKdK/U8rN35YgEknYGVmPGES0YRduBIOYS/kw5fL23PKBRtCjSOJNcyeOHDobeuQfzm 9Z5rF1dYogxlQeXzXNDKSpzpD3NZgWMFZGJr42KmZY6DMFyNfsvTO2Hoobun9SfnEROY Kn678VlSv8mLiXdRDsL5tinQz9l0JWBmSZk4JVuvSwhXaS0FhI6Pbk0GFMpZNo7ni4AC a4fg== X-Gm-Message-State: AC+VfDz0kVxCsRaidPr3s06KZ2wKrtgI7T08RUsDTsZjapU2xaTwJ2iJ xAllIbC0WUGeAA0kpsra82MlRonovFpVzVcNteM= X-Google-Smtp-Source: ACHHUZ6eQPbuzGsybTDXBU2zHVGN0hkZzUyE4JaZy+QaROkB0HmhbMbya34v7JUSD6IaKqzc73idjw== X-Received: by 2002:a92:c144:0:b0:33a:f1b2:eb6c with SMTP id b4-20020a92c144000000b0033af1b2eb6cmr6666550ilh.3.1685636679039; Thu, 01 Jun 2023 09:24:39 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:38 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 15/40] cat: Update command to use fs_load_alloc() Date: Thu, 1 Jun 2023 10:22:39 -0600 Message-ID: <20230601162404.220488-14-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Use this new function since it implements the required functionality and reduces duplicated code. Signed-off-by: Simon Glass --- cmd/cat.c | 47 +++++++++++++++++------------------------------ 1 file changed, 17 insertions(+), 30 deletions(-) diff --git a/cmd/cat.c b/cmd/cat.c index 1273a26b1457..b059080193d4 100644 --- a/cmd/cat.c +++ b/cmd/cat.c @@ -17,8 +17,8 @@ static int do_cat(struct cmd_tbl *cmdtp, int flag, int argc, char *dev; char *file; char *buffer; - phys_addr_t addr; - loff_t file_size; + ulong file_size; + int ret; if (argc < 4) return CMD_RET_USAGE; @@ -27,40 +27,27 @@ static int do_cat(struct cmd_tbl *cmdtp, int flag, int argc, dev = argv[2]; file = argv[3]; + ret = fs_load_alloc(ifname, dev, file, 0, 0, (void **)&buffer, + &file_size); + // check file exists - if (fs_set_blk_dev(ifname, dev, FS_TYPE_ANY)) + switch (ret) { + case 0: + break; + case -ENOMEDIUM: return CMD_RET_FAILURE; - - if (!fs_exists(file)) { + case -ENOENT: log_err("File does not exist: ifname=%s dev=%s file=%s\n", ifname, dev, file); return CMD_RET_FAILURE; - } - - // get file size - if (fs_set_blk_dev(ifname, dev, FS_TYPE_ANY)) + case -E2BIG: + log_err("File is too large: ifname=%s dev=%s file=%s\n", ifname, dev, file); return CMD_RET_FAILURE; - - if (fs_size(file, &file_size)) { - log_err("Cannot read file size: ifname=%s dev=%s file=%s\n", ifname, dev, file); + case -ENOMEM: + log_err("Not enough memory: ifname=%s dev=%s file=%s\n", ifname, dev, file); return CMD_RET_FAILURE; - } - - // allocate memory for file content - buffer = calloc(sizeof(char), file_size + 1); - if (!buffer) { - log_err("Out of memory\n"); - return CMD_RET_FAILURE; - } - - // map pointer to system memory - addr = map_to_sysmem(buffer); - - // read file to memory - if (fs_set_blk_dev(ifname, dev, FS_TYPE_ANY)) - return CMD_RET_FAILURE; - - if (fs_read(file, addr, 0, 0, &file_size)) { - log_err("Cannot read file: ifname=%s dev=%s file=%s\n", ifname, dev, file); + default: + case -EIO: + log_err("File-read failed: ifname=%s dev=%s file=%s\n", ifname, dev, file); return CMD_RET_FAILURE; } From patchwork Thu Jun 1 16:22:40 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789232 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=AeevYSs8; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBPl5Zsmz20Py for ; Fri, 2 Jun 2023 02:27:55 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id BCEE986385; Thu, 1 Jun 2023 18:25:20 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="AeevYSs8"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 8E84386377; Thu, 1 Jun 2023 18:24:47 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x132.google.com (mail-il1-x132.google.com [IPv6:2607:f8b0:4864:20::132]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 46EAD86347 for ; Thu, 1 Jun 2023 18:24:43 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x132.google.com with SMTP id e9e14a558f8ab-33bb16ac2e9so3414215ab.3 for ; Thu, 01 Jun 2023 09:24:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636680; x=1688228680; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Ng7NFxbmbklJFs0i91wGa+tO0NSwYieGmrYcbB75NUA=; b=AeevYSs8C+BiVASHwzB6i53fYCm4HyMk4l2S3hAWT7xS+Uzi1ZiaUG6gARzilnLg+I JkD2izIqEWNEv27qnGzYr2gH8X5oUwY3WYAIbU1psAXYEAYE1oRHTgo3jJJO9iraWqTC JtZCfUKnBfPqRP3JQXMIX8nhVJnLQ932ExxFc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636680; x=1688228680; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Ng7NFxbmbklJFs0i91wGa+tO0NSwYieGmrYcbB75NUA=; b=YgKH3Fn4JuvcscF+cuYbUhFeJjbyaTlZ8xsZuKrTpiq/ZIcQI+fIde4j26GkvenycD IvyX3oF/PnbfB9UsSlukqJyVqnu2Vg7zBBLRB7/ZQIdNG80SYT/E4dNKZ+N3fGLsBN+j Xy2msvqL0hKQppb3Qi3UtFuvYhokmb8xARnQcanrQRoLVMY9cIJ3+sovhsVJWdlsXysR E+x3rsaPLynWqcIPYL/iBDNMtmdpfGY7EtEjFIBdC2q2Y8MRfUlMeFXu/VSDijtT/+bB YCADM1gtVQz/Ho91AQ8s2PzCfHmui6nMV8/fNQNGav1azHm8i2jXSvfNDZbwDlt9dNah 82Gg== X-Gm-Message-State: AC+VfDwKFXDtyiZQAdTqUvqGdIfZcjmr5KQYcoMbKQh1xqbjjBEmnXz6 66trcyLGaZa+ncdb1zelP9C7NC3s5/7w72Ca9dM= X-Google-Smtp-Source: ACHHUZ72TWMWeukqLpG2eqFsQmDf7bdXyje6nw02hDRDu6yOEaIPNB6q2QLMKW5nXz4Mukcf2fug5w== X-Received: by 2002:a92:d90e:0:b0:334:c74c:43f9 with SMTP id s14-20020a92d90e000000b00334c74c43f9mr4863290iln.13.1685636679824; Thu, 01 Jun 2023 09:24:39 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:39 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass , Jerry Van Baren Subject: [PATCH 16/40] fdt: Align the start of the livetree Date: Thu, 1 Jun 2023 10:22:40 -0600 Message-ID: <20230601162404.220488-15-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Ensure that the block of memory used by live tree is aligned according to the default for structures. This ensures that the root node appears at the start of the block, so it can be used with free(), rather than being 4 bytes later in some cases. This corrects a rather obscure bug in unflatten_device_tree(). Fixes: 8b50d526ea5 ("dm: Add a function to create a 'live' device tree") Signed-off-by: Simon Glass --- include/dm/of.h | 2 ++ lib/of_live.c | 5 ++++- test/dm/ofnode.c | 26 ++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/include/dm/of.h b/include/dm/of.h index fce7cef0ff69..b1c934f610d3 100644 --- a/include/dm/of.h +++ b/include/dm/of.h @@ -63,6 +63,8 @@ struct device_node { struct device_node *sibling; }; +#define BAD_OF_ROOT 0xdead11e3 + #define OF_MAX_PHANDLE_ARGS 16 /** diff --git a/lib/of_live.c b/lib/of_live.c index 1b5964d09a9d..05588d5ed282 100644 --- a/lib/of_live.c +++ b/lib/of_live.c @@ -287,9 +287,12 @@ int unflatten_device_tree(const void *blob, struct device_node **mynodes) debug(" size is %lx, allocating...\n", size); /* Allocate memory for the expanded device tree */ - mem = malloc(size + 4); + mem = memalign(__alignof__(struct device_node), size + 4); memset(mem, '\0', size); + /* Set up value for dm_test_livetree_align() */ + *(u32 *)mem = BAD_OF_ROOT; + *(__be32 *)(mem + size) = cpu_to_be32(0xdeadbeef); debug(" unflattening %p...\n", mem); diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c index 473a8cef5780..64baaf68db3a 100644 --- a/test/dm/ofnode.c +++ b/test/dm/ofnode.c @@ -1240,3 +1240,29 @@ static int dm_test_ofnode_copy_props_ot(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_ofnode_copy_props_ot, UT_TESTF_SCAN_FDT | UT_TESTF_OTHER_FDT); + +/* check that the livetree is aligned to a structure boundary */ +static int dm_test_livetree_align(struct unit_test_state *uts) +{ + const int align = __alignof__(struct unit_test_state); + struct device_node *node; + u32 *sentinel; + ulong start; + + start = (ulong)gd_of_root(); + ut_asserteq(start, ALIGN(start, align)); + + node = gd_of_root(); + sentinel = (void *)node - sizeof(u32); + + /* + * The sentinel should be overwritten with the root node. If it isn't, + * then the root node is not at the very start of the livetree memory + * area, and free(root) will fail to free the memory used by the + * livetree. + */ + ut_assert(*sentinel != BAD_OF_ROOT); + + return 0; +} +DM_TEST(dm_test_livetree_align, UT_TESTF_LIVE_TREE); From patchwork Thu Jun 1 16:22:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789229 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=XXHBqQTw; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBPB1tT2z20QB for ; Fri, 2 Jun 2023 02:27:26 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id B969A863B0; Thu, 1 Jun 2023 18:25:13 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="XXHBqQTw"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id A5F7E86339; Thu, 1 Jun 2023 18:24:44 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x136.google.com (mail-il1-x136.google.com [IPv6:2607:f8b0:4864:20::136]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 410AA8615F for ; Thu, 1 Jun 2023 18:24:41 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x136.google.com with SMTP id e9e14a558f8ab-33b9a56e261so4027195ab.0 for ; Thu, 01 Jun 2023 09:24:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636680; x=1688228680; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=BUtaa6SrNhFKgiYEWhdF6Tyr7MHLp3I5j2IUd4bhAuA=; b=XXHBqQTwrpp5YHcu4UiczRGuP2W9PMy9mk2yZz1bJk6YG73bfnTpvU/nhJK/PfFg6O Lwa/Z5EE8yiBEwrknLSDgQZJz1tiwXKpSx8Qgc7RlUsZ6RtZhAPOuG28TdI4EdBmCto0 EqOTZu9A/SwgxeoiInVPHjjkq/muoqpR+gZJI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636680; x=1688228680; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=BUtaa6SrNhFKgiYEWhdF6Tyr7MHLp3I5j2IUd4bhAuA=; b=ddmDaa3xwYsOOax+xLpM2XB3RaN2HxhbfgFNAbDz+4U4UudUazP0mrJOZ29MnVGnVn zPpy4WYGjbzavj1nEnDpniq3Xof2syBLHQCe1AaBndKqDttJmnMAUZaHoDTzMHKk1UCS /Nsya785pWgv9642SRKkA7f40HbgOqOCyOJ4elObaGnDMNzyHAjf/g649Q8v3WtdTaQI fjcLIQG2vuKFo74exafoNIOA5dUzisHUNmDMSqVyfrc0ycwmbGzmv8rotRYwbed2ARfa Q4CipQHBqb4aZNwLZOly86KY3A+AXyjS/FSrB+14X+dmhOdr53pE0m5dJsyz/clMm2Sm MQEg== X-Gm-Message-State: AC+VfDyXycS1lAIrcQd/3+nSfj7g8H1BYluA1GSJjfs0k/RuRoPtrTFz 2JroOwJRiXd+VroR4wImKoGAsaUIJqnokyeFpVw= X-Google-Smtp-Source: ACHHUZ766HLQsPapTdNTIq4wI9c3x93WilpY9cowUHthplk3NdFJf1IEDAQ93OAU3DgI46gRz/jo4Q== X-Received: by 2002:a92:c6c3:0:b0:332:b18a:7ba7 with SMTP id v3-20020a92c6c3000000b00332b18a7ba7mr5933938ilm.27.1685636680772; Thu, 01 Jun 2023 09:24:40 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:40 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass , Jerry Van Baren Subject: [PATCH 17/40] fdt: Clarify the fdt pre-relocation warning Date: Thu, 1 Jun 2023 10:22:41 -0600 Message-ID: <20230601162404.220488-16-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Reword this so it is easier to understand. Signed-off-by: Simon Glass --- drivers/core/ofnode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 1d4ab5bb6f2f..dee890b5527b 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -72,7 +72,7 @@ static oftree oftree_ensure(void *fdt) } } else { if (fdt != gd->fdt_blob) { - log_debug("Cannot only access control FDT before relocation\n"); + log_debug("Only the control FDT can be accessed before relocation\n"); return oftree_null(); } } From patchwork Thu Jun 1 16:22:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789237 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=BhuFxU41; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBR06G84z20Py for ; Fri, 2 Jun 2023 02:29:00 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 2FEF0863A5; Thu, 1 Jun 2023 18:25:33 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="BhuFxU41"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id AC5C986345; Thu, 1 Jun 2023 18:24:56 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x135.google.com (mail-il1-x135.google.com [IPv6:2607:f8b0:4864:20::135]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id E1C1586369 for ; Thu, 1 Jun 2023 18:24:51 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x135.google.com with SMTP id e9e14a558f8ab-33b04c8f3eeso3396415ab.0 for ; Thu, 01 Jun 2023 09:24:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636681; x=1688228681; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Y3odaVOEX2pog6bi/3962/fOAXLWFyJ4XUjMBeBtFWk=; b=BhuFxU41AqUcusprAjL3RNjvWM02yi70+39QOXY1djyExVtM8w3LWD7DNZ/EBVr3Ez bnVJZpP6eZQpu9LEtXO773dX1j8gTg7Jhf69YT6WsYvtf62V96VUaiL3yCJNhza3pszI ORv6YXzhkj/f7BZakaaZZ6P6dsHgaeAy8OboQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636681; x=1688228681; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Y3odaVOEX2pog6bi/3962/fOAXLWFyJ4XUjMBeBtFWk=; b=hQ2Vei213GD4uBVfZga1S5KYnHE7xbmmovQ2QExYfVL8wZQnshif01hXEJEuznPTY9 GHJC3mPRtEZHhUaXOwAQImUp2ipJWVczvQCyvz1ReUvGe6pF7SNmQ1xGY0VQGoSvdCXC Rv/bKZj/JbMc/VdQdKSg/qTbPXwRjwBf4FYIQoMhNG6xjk1NA1W3kw6YuydfnjwlwhM9 r1/b1CCReHfFck6Ro2Hbnh5qlqFhQ9MBUaG047Cpd83NGhYC2fJxVYF/ybFZTK4PE7/N rvrHzM05umfuc6Q/A2z8zCpjNniLSAE5CniqWYiY+0hR/NsUDrAllXDrDZyhcscyzvLM 9atw== X-Gm-Message-State: AC+VfDyixxjmYamD7C6EduPYahUXppMhiPbzl8B3MmKcZiaVNstlxZmZ 8wZHp+xgtOtfYoBHOSYdeyKieupqFgjgCgmvHFk= X-Google-Smtp-Source: ACHHUZ7tlnU0DBd//uox/keWUwVSKhvttfyBlV6tfLJI/f9Bomz7+cJpmQPpM/tYhogfJGKGjmOO5A== X-Received: by 2002:a92:c009:0:b0:33b:424a:eb41 with SMTP id q9-20020a92c009000000b0033b424aeb41mr5400590ild.2.1685636681703; Thu, 01 Jun 2023 09:24:41 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:41 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass , Jerry Van Baren Subject: [PATCH 18/40] fdt: Allow more general use of livetree Date: Thu, 1 Jun 2023 10:22:42 -0600 Message-ID: <20230601162404.220488-17-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean At present livetree can only be used for the control FDT. It is useful to be able to use the ofnode API for other FDTs, e.g. those used by the upcoming configuration editor. We already have most of the support present, and tests can be marked with the UT_TESTF_OTHER_FDT flag to use another FDT as a special case. But with this change, the functionality becomes more generally available. Plumb in the require support. Signed-off-by: Simon Glass --- drivers/core/ofnode.c | 26 +++++++++++++++++++++----- include/dm/ofnode.h | 10 ++++++++++ include/of_live.h | 10 ++++++++++ lib/of_live.c | 6 ++++++ test/dm/ofnode.c | 19 +++++++++++++++++++ 5 files changed, 66 insertions(+), 5 deletions(-) diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index dee890b5527b..8df16e56af5c 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +52,20 @@ static oftree oftree_ensure(void *fdt) oftree tree; int i; + if (of_live_active()) { + struct device_node *root; + int ret; + + ret = unflatten_device_tree(fdt, &root); + if (ret) { + log_err("Failed to create live tree: err=%d\n", ret); + return oftree_null(); + } + tree = oftree_from_np(root); + + return tree; + } + if (gd->flags & GD_FLG_RELOC) { i = oftree_find(fdt); if (i == -1) { @@ -60,11 +75,6 @@ static oftree oftree_ensure(void *fdt) return oftree_null(); } - if (of_live_active()) { - log_err("Cannot register a flattree when OF_LIVE is active\n"); - return oftree_null(); - } - /* register the new tree */ i = oftree_count++; oftree_list[i] = fdt; @@ -82,6 +92,12 @@ static oftree oftree_ensure(void *fdt) return tree; } +void oftree_dispose(oftree tree) +{ + if (of_live_active()) + of_live_free(tree.np); +} + void *ofnode_lookup_fdt(ofnode node) { if (gd->flags & GD_FLG_RELOC) { diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h index 443db6252ddc..0f38b3e736de 100644 --- a/include/dm/ofnode.h +++ b/include/dm/ofnode.h @@ -352,6 +352,16 @@ static inline oftree oftree_from_np(struct device_node *root) return tree; } +/** + * oftree_dispose() - Dispose of an oftree + * + * This can be used to dispose of a tree that has been created (other than + * the control FDT which must not be disposed) + * + * @tree: Tree to dispose + */ +void oftree_dispose(oftree tree); + /** * ofnode_name_eq() - Check if the node name is equivalent to a given name * ignoring the unit address diff --git a/include/of_live.h b/include/of_live.h index f59d6af3350d..05e86ac06b1a 100644 --- a/include/of_live.h +++ b/include/of_live.h @@ -36,4 +36,14 @@ int of_live_build(const void *fdt_blob, struct device_node **rootp); */ int unflatten_device_tree(const void *blob, struct device_node **mynodes); +/** + * of_live_free() - Dispose of a livetree + * + * This frees memory used by the tree, after which @root becomes invalid and + * cannot be used + * + * @root: Tree to dispose + */ +void of_live_free(struct device_node *root); + #endif diff --git a/lib/of_live.c b/lib/of_live.c index 05588d5ed282..25f7af61061e 100644 --- a/lib/of_live.c +++ b/lib/of_live.c @@ -330,3 +330,9 @@ int of_live_build(const void *fdt_blob, struct device_node **rootp) return ret; } + +void of_live_free(struct device_node *root) +{ + /* the tree is stored as a contiguous block of memory */ + free(root); +} diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c index 64baaf68db3a..6fbebc7da085 100644 --- a/test/dm/ofnode.c +++ b/test/dm/ofnode.c @@ -1266,3 +1266,22 @@ static int dm_test_livetree_align(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_livetree_align, UT_TESTF_LIVE_TREE); + +/* check that it is possible to load an arbitrary livetree */ +static int dm_test_livetree_ensure(struct unit_test_state *uts) +{ + oftree tree; + ofnode node; + + /* read from other.dtb */ + ut_assertok(test_load_other_fdt(uts)); + tree = oftree_from_fdt(uts->other_fdt); + ut_assert(oftree_valid(tree)); + node = oftree_path(tree, "/node/subnode"); + ut_assert(ofnode_valid(node)); + ut_asserteq_str("sandbox-other2", + ofnode_read_string(node, "compatible")); + + return 0; +} +DM_TEST(dm_test_livetree_ensure, 0); From patchwork Thu Jun 1 16:22:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789239 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=RmzmX9L7; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBRW0m7Bz20Py for ; Fri, 2 Jun 2023 02:29:27 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 0BEA0863D7; Thu, 1 Jun 2023 18:25:40 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="RmzmX9L7"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 9856986394; Thu, 1 Jun 2023 18:25:10 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x12e.google.com (mail-il1-x12e.google.com [IPv6:2607:f8b0:4864:20::12e]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 213EE86373 for ; Thu, 1 Jun 2023 18:25:00 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x12e.google.com with SMTP id e9e14a558f8ab-33aa60f4094so4105225ab.1 for ; Thu, 01 Jun 2023 09:25:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636682; x=1688228682; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ZQsQRJXc80rjyHJppL4ET2leFcrhYRG9i31CWh5UjrQ=; b=RmzmX9L7dYVg1VlwQD6hUaj/mSaXV9u0mjMyBMJeHo06YJFJ0fHbs1W6KArda57mR5 COVnQRgt6ZM6/JmcYdQwtkDNuPSfrZjHQir+OqMRYMpe0/mI7DlLwP6hBaXbPTIT+lbL evc1Y/gY15g0HQDSNCBoP+ylXBLtUf2AlAxxI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636682; x=1688228682; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ZQsQRJXc80rjyHJppL4ET2leFcrhYRG9i31CWh5UjrQ=; b=EoZmJ54yyf05NemXrjgPiXgYI6f6YEkufk6UcRWE32bssosSbu+h0ZI6xZXuJ98AFl OWFPB1qJa9HAmTcAetdqmBWC3zyv1myjdLU1re+bXKhVzOJPTZpGMiBGvtqpsB5qi58C u1KEcb/Tr1kdg4bhx2MzGKqFT7ZNiqEDbGym8htZEhh8FoF1IY0YoudFGwJv6vvXC2rF w4faGAPgb5gUymZTHIm8XDj13hFp6rBugORzCj4LDXNeKudUaYOtsZ0N3cMy2ClbHPAp Yt3ZevFxp1NSUuWEmqSE12/rc8eT9cplaE3obh+5JVR71V/D0sXFBLfOFUbyAhnNWAsB xk9A== X-Gm-Message-State: AC+VfDxQ7kE4jOv2zAlBzMN16fi7l3FIOnrmUhXjd5+RjJ1lcnW+TlUP THEGC9JJo6KwqE3pzc2+Q3vHI1jzuPcDrtx8HQU= X-Google-Smtp-Source: ACHHUZ47fWbP0yKI4OZgqJNOQL0OWKvV3oyvux8S4hRKy0ifRrKqtwO3Y7gE7L2mCNvzuy/MiSic1A== X-Received: by 2002:a92:d441:0:b0:330:dc10:9c01 with SMTP id r1-20020a92d441000000b00330dc109c01mr2553265ilm.11.1685636682488; Thu, 01 Jun 2023 09:24:42 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:42 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 19/40] bootstd: Add a separate log category for expo Date: Thu, 1 Jun 2023 10:22:43 -0600 Message-ID: <20230601162404.220488-18-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean This feature is different enough from bootstd that it probably deserves its own log category. It cannot use a uclass since it is not a device. Add a new category. Signed-off-by: Simon Glass --- boot/expo.c | 2 ++ boot/scene.c | 2 ++ boot/scene_menu.c | 2 +- common/log.c | 1 + include/log.h | 2 ++ 5 files changed, 8 insertions(+), 1 deletion(-) diff --git a/boot/expo.c b/boot/expo.c index e7c81a3983d3..8b966b6c793c 100644 --- a/boot/expo.c +++ b/boot/expo.c @@ -6,6 +6,8 @@ * Written by Simon Glass */ +#define LOG_CATEGORY LOGC_EXPO + #include #include #include diff --git a/boot/scene.c b/boot/scene.c index 1383be20321f..43c978e6ee80 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -6,6 +6,8 @@ * Written by Simon Glass */ +#define LOG_CATEGORY LOGC_EXPO + #include #include #include diff --git a/boot/scene_menu.c b/boot/scene_menu.c index 9ee911f2fa38..8b04d4403139 100644 --- a/boot/scene_menu.c +++ b/boot/scene_menu.c @@ -6,7 +6,7 @@ * Written by Simon Glass */ -#define LOG_CATEGORY LOGC_BOOT +#define LOG_CATEGORY LOGC_EXPO #include #include diff --git a/common/log.c b/common/log.c index 7cfc49bc28a5..6f02a25c5931 100644 --- a/common/log.c +++ b/common/log.c @@ -31,6 +31,7 @@ static const char *const log_cat_name[] = { "boot", "event", "fs", + "expo", }; _Static_assert(ARRAY_SIZE(log_cat_name) == LOGC_COUNT - LOGC_NONE, diff --git a/include/log.h b/include/log.h index 3bab40b61715..6e84f080ef3d 100644 --- a/include/log.h +++ b/include/log.h @@ -102,6 +102,8 @@ enum log_category_t { LOGC_EVENT, /** @LOGC_FS: Related to filesystems */ LOGC_FS, + /** @LOGC_EXPO: Related to expo handling */ + LOGC_EXPO, /** @LOGC_COUNT: Number of log categories */ LOGC_COUNT, /** @LOGC_END: Sentinel value for lists of log categories */ From patchwork Thu Jun 1 16:22:44 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789238 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=CrLeFAUw; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBRG3dPdz20Py for ; Fri, 2 Jun 2023 02:29:14 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 1968B863CA; Thu, 1 Jun 2023 18:25:36 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="CrLeFAUw"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 48C408639E; Thu, 1 Jun 2023 18:25:09 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x12f.google.com (mail-il1-x12f.google.com [IPv6:2607:f8b0:4864:20::12f]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 970958631B for ; Thu, 1 Jun 2023 18:25:03 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x12f.google.com with SMTP id e9e14a558f8ab-33be5dbb90cso3671315ab.0 for ; Thu, 01 Jun 2023 09:25:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636683; x=1688228683; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=9TalzAqDVGNoRg/MU39b1guS/V3oxpjuJWyXlDkAtqw=; b=CrLeFAUwRsD1SJ9Mjt5ZTYem/57UB0ua5OQKbtvayWX0vsuwXngMhwAs6gqcmbivfh S3rmlWx621ceDXpoRiq7YYgmRvhT0la+lyMdlF8ciwyHkfMW5jpmb3GwIclaCeSlf1zx FqBvI4tv9Ur5WzT6DRMfsEvSrc8Ml7gtU8AOs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636683; x=1688228683; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=9TalzAqDVGNoRg/MU39b1guS/V3oxpjuJWyXlDkAtqw=; b=Yc9UbbJ8yQWRvzxF38plc1gDoh/3h17ZFbykrCL1xZgECGY+neWEMgQLN1aTPLedzi qAdQGJxi71BraoSEZKiBn68kQo4sla+7drFV5ARRPX6GaIFaJ1EzGzhz9O7xjuEL1g0+ ltpJv2puTqGGeA6wBQ3yYiVWZaPxo1kfKkJ6nmkw1Xw6uVzsYVtd3AtL002LI/hfslcZ nX81WnKei/66P03ZcneSWb9iova8XmERt5K6vQqVNUrSiFAHJHTmq3djjPhP1vk1+cF8 WUtOVJQtwq//dfFoXLIcPGJdQT3qFqdi7a98+Ba9lJbwfNyo4GPwCw+2omUnzDI2TsPb +zig== X-Gm-Message-State: AC+VfDy1r7SZQ4Oc5boTCnDvz5o8NTKWdBkBd6olAyR3AlaspsKRm/Qr 9bJNmVP20FwOtiucDrbC8YMtSjm88szAh8Z4Z0c= X-Google-Smtp-Source: ACHHUZ5Ner+1I9JlcaY9+nsAvbgkHfeP36F2RWaZCjVMOHeOZ2mMXSllg0e7RzbGeBSkOxz94xpJnQ== X-Received: by 2002:a92:d405:0:b0:338:b9a1:5d06 with SMTP id q5-20020a92d405000000b00338b9a15d06mr4958178ilm.2.1685636683322; Thu, 01 Jun 2023 09:24:43 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:43 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass , Anatolij Gustschin Subject: [PATCH 20/40] video: Correct docs for video_index_to_colour() Date: Thu, 1 Jun 2023 10:22:44 -0600 Message-ID: <20230601162404.220488-19-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean This uses the private data of the video uclass, not the console uclass (its child). Update the comment to avoid confusion. Signed-off-by: Simon Glass Fixes: a032e4b55ea ("video: Move console colours to the video uclass") --- include/video.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/video.h b/include/video.h index e5b0db294734..dd0d55baa31a 100644 --- a/include/video.h +++ b/include/video.h @@ -162,7 +162,7 @@ enum colour_idx { * The caller has to guarantee that the color index is less than * VID_COLOR_COUNT. * - * @priv private data of the console device + * @priv private data of the video device (UCLASS_VIDEO) * @idx color index * Return: color value */ From patchwork Thu Jun 1 16:22:45 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789241 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=CSF5IiSI; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBS01MQhz20Py for ; Fri, 2 Jun 2023 02:29:52 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id A5FEB865BB; Thu, 1 Jun 2023 18:25:46 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="CSF5IiSI"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id CFAFC86358; Thu, 1 Jun 2023 18:25:16 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mail-il1-x131.google.com (mail-il1-x131.google.com [IPv6:2607:f8b0:4864:20::131]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 9175086383 for ; Thu, 1 Jun 2023 18:25:04 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x131.google.com with SMTP id e9e14a558f8ab-33b5dba8c6cso3415495ab.2 for ; Thu, 01 Jun 2023 09:25:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636684; x=1688228684; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=5b0kTaAkYbxIu9zF6TWjDBfix0YhWgdp7hPIQrsAAwE=; b=CSF5IiSIDNThtHSxxYzsoYyD5e4c8DonDR0JONnfU8+tZXo8rCyqNIvFfEF2EVc1CP 3S7bKeH0QdZxT0eayzh9G4omzTaQNyCcVSRMXiRBR9WdOPz6DPh3f29SSmsz5eQn7qwk OzvydBujir9f9/FWd5nmE7L0B3PKc/rY1D41U= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636684; x=1688228684; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=5b0kTaAkYbxIu9zF6TWjDBfix0YhWgdp7hPIQrsAAwE=; b=e/8M1Ao/VrApcQsAtbUO0EA7zyKBPwPLsBLpaz8LjbrjD3GgFSUbOhlpdKM74lA+LZ nPchvjM5p9qF5oKMQm/0PYYCYPSupKrPXUPTK6xhAqFTLMx3cvdh52Yf3khcTLNdR5bD nUVj4xc8nY8shpokATY0HV/ygzDbWT5WliIQA9vybH9fr9GH8pHzE2V3GufTV4uLSKRd 3q3oNju1FHIGaqsTz8imYKE6se5wnb1S3mlnK4+xc3ARr/Huf2Fynk17qU4y47JBCO9O p/J6j+0SvoK95NrvoGHWXUu1MCVL17ROES2l/eENSFDE+lGSScg2HggvHb47p8i1rv3Q Ao6Q== X-Gm-Message-State: AC+VfDwoH/BV0KwpMzpSG+O6XjohidMhLSAQR6BggPI63kvrT+r0nbmQ J0U0EsM8Q13qHegTwGqiIPwR3/XjWniTOT1798w= X-Google-Smtp-Source: ACHHUZ5nNKpEMZCLvtRdAh7uBIzUYWiiEKAbHujs6nYAOSaWIiH0Qgbmosxep6x/YkDh2xgpxTMemw== X-Received: by 2002:a92:d90e:0:b0:334:c74c:43f9 with SMTP id s14-20020a92d90e000000b00334c74c43f9mr4863418iln.13.1685636684112; Thu, 01 Jun 2023 09:24:44 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:43 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass , Anatolij Gustschin Subject: [PATCH 21/40] video: Allow temporary colour changes Date: Thu, 1 Jun 2023 10:22:45 -0600 Message-ID: <20230601162404.220488-20-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean It is sometimes necessary to highlight some text in a different colour. Add an easy way to do this and then restore the original console colours. Signed-off-by: Simon Glass --- drivers/video/vidconsole-uclass.c | 20 ++++++++++++++++++++ include/video_console.h | 30 ++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index a21fde0e1d46..3f89537c47b7 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -596,6 +596,26 @@ int vidconsole_select_font(struct udevice *dev, const char *name, uint size) return ops->select_font(dev, name, size); } +void vidconsole_push_colour(struct udevice *dev, enum colour_idx fg, + enum colour_idx bg, struct vidconsole_colour *old) +{ + struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); + + old->colour_fg = vid_priv->colour_fg; + old->colour_bg = vid_priv->colour_bg; + + vid_priv->colour_fg = video_index_to_colour(vid_priv, fg); + vid_priv->colour_bg = video_index_to_colour(vid_priv, bg); +} + +void vidconsole_pop_colour(struct udevice *dev, struct vidconsole_colour *old) +{ + struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); + + vid_priv->colour_fg = old->colour_fg; + vid_priv->colour_bg = old->colour_bg; +} + /* Set up the number of rows and colours (rotated drivers override this) */ static int vidconsole_pre_probe(struct udevice *dev) { diff --git a/include/video_console.h b/include/video_console.h index 3db9a7e1fb95..81d4c4d874df 100644 --- a/include/video_console.h +++ b/include/video_console.h @@ -71,6 +71,17 @@ struct vidfont_info { const char *name; }; +/** + * struct vidconsole_colour - Holds colour information + * + * @colour_fg: Foreground colour (pixel value) + * @colour_bg: Background colour (pixel value) + */ +struct vidconsole_colour { + u32 colour_fg; + u32 colour_bg; +}; + /** * struct vidconsole_ops - Video console operations * @@ -204,6 +215,25 @@ int vidconsole_get_font(struct udevice *dev, int seq, */ int vidconsole_select_font(struct udevice *dev, const char *name, uint size); +/** + * vidconsole_push_colour() - Temporarily change the font colour + * + * @dev: Device to adjust + * @fg: Foreground colour to select + * @bg: Background colour to select + * @old: Place to store the current colour, so it can be restored + */ +void vidconsole_push_colour(struct udevice *dev, enum colour_idx fg, + enum colour_idx bg, struct vidconsole_colour *old); + +/** + * vidconsole_pop_colour() - Restore the original colour + * + * @dev: Device to adjust + * @old: Old colour to be restored + */ +void vidconsole_pop_colour(struct udevice *dev, struct vidconsole_colour *old); + /** * vidconsole_putc_xy() - write a single character to a position * From patchwork Thu Jun 1 16:22:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789240 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=T/1ADud1; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBRl2SGJz20Py for ; Fri, 2 Jun 2023 02:29:39 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 72054865B7; Thu, 1 Jun 2023 18:25:43 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="T/1ADud1"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 8CF70863A4; Thu, 1 Jun 2023 18:25:14 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x131.google.com (mail-il1-x131.google.com [IPv6:2607:f8b0:4864:20::131]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 7CA5086328 for ; Thu, 1 Jun 2023 18:25:04 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x131.google.com with SMTP id e9e14a558f8ab-33b4552e55cso4156875ab.0 for ; Thu, 01 Jun 2023 09:25:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636685; x=1688228685; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=bwkXYg5rj8FqJuPPoClij704zeYx67KSADrARmkLNqY=; b=T/1ADud1jBqrsOgLSgIRkLJRlVf2ZvQL5EB0kUz19nXVAUPMO1D9Q8mv67PCSAaRdy 1UUtymR0oVeXSGLcPGrr+1gOJ6xd8pJ5rhlg1hWe79nvno45neDdFdjWnyID4lnSRL7f ZMxQvXaYrCAliXJiUsaP8l+yhIDbBYbeJTBhQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636685; x=1688228685; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=bwkXYg5rj8FqJuPPoClij704zeYx67KSADrARmkLNqY=; b=J31XqdRBqu5rUhsKV9iZ4y/ujj1BcK9+ts3nIsXgJWdWe0kW39VAJI8o2WjIgQVzoi y3bx2vBbipN7vIprgx5ZrckkxxeQtIAhujz2OcgffbEyh9TnD4D76Cqa2h1yaTDW8EsY L5z8jvZajq7U8IQhJ0PssGkEdEnzGR5yZWwchEUX4llVWsfwt3XFE/9331d32tXtAtqI 595iuR6Fjwq35WkzDLRKjc5au0l1BtSPYtERGTGycCoBb3yIMfd4FM1uP8KdLGO2ekib S3JIHJSy5nNNTgzJnr8uGC8iGapitm0Xj44HN/pLV9mVnMZUwghnbYqilodMvUrHt4yA m1Mw== X-Gm-Message-State: AC+VfDxO3d9tNv7/7IQ0cK6r7rtLgrbPFDjh+6vS+JIY8mcDqaq42WBl qBuRVQihWq7Rrpn3X/0Jzw/Gw+aSWIU6013cTgE= X-Google-Smtp-Source: ACHHUZ7uJJp7P/CKz1lrx+eh+ZA8x8VNW929GY2zyOBDcQ/DEh4s2UqWFg4EgQp9UJ4ureXTmIFMAQ== X-Received: by 2002:a92:c845:0:b0:334:de38:d600 with SMTP id b5-20020a92c845000000b00334de38d600mr2531163ilq.3.1685636684940; Thu, 01 Jun 2023 09:24:44 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:44 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 22/40] console: Allow measuring the bounding box of text Date: Thu, 1 Jun 2023 10:22:46 -0600 Message-ID: <20230601162404.220488-21-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean For laying out text accurately it is necessary to know the width and height of the text. Add a measure() method to the console API, so this can be supported. Add an implementation for truetype and a base implementation for the normal console. Signed-off-by: Simon Glass --- drivers/video/console_truetype.c | 64 ++++++++++++++++++++++++++++++- drivers/video/vidconsole-uclass.c | 22 +++++++++++ include/video_console.h | 48 +++++++++++++++++++++++ 3 files changed, 132 insertions(+), 2 deletions(-) diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c index 6f3fc82f9b05..288123a2e065 100644 --- a/drivers/video/console_truetype.c +++ b/drivers/video/console_truetype.c @@ -614,8 +614,8 @@ static void select_metrics(struct udevice *dev, struct console_tt_metrics *met) vc_priv->tab_width_frac = VID_TO_POS(met->font_size) * 8 / 2; } -static int truetype_select_font(struct udevice *dev, const char *name, - uint size) +static int get_metrics(struct udevice *dev, const char *name, uint size, + struct console_tt_metrics **metp) { struct console_tt_priv *priv = dev_get_priv(dev); struct console_tt_metrics *met; @@ -653,11 +653,70 @@ static int truetype_select_font(struct udevice *dev, const char *name, met = priv->metrics; } + *metp = met; + + return 0; +} + +static int truetype_select_font(struct udevice *dev, const char *name, + uint size) +{ + struct console_tt_metrics *met; + int ret; + + ret = get_metrics(dev, name, size, &met); + if (ret) + return log_msg_ret("sel", ret); + select_metrics(dev, met); return 0; } +int truetype_measure(struct udevice *dev, const char *name, uint size, + const char *text, struct vidconsole_bbox *bbox) +{ + struct console_tt_metrics *met; + stbtt_fontinfo *font; + int lsb, advance; + const char *s; + int width; + int last; + int ret; + + ret = get_metrics(dev, name, size, &met); + if (ret) + return log_msg_ret("sel", ret); + + bbox->valid = false; + if (!*text) + return 0; + + font = &met->font; + width = 0; + for (last = 0, s = text; *s; s++) { + int ch = *s; + + /* Used kerning to fine-tune the position of this character */ + if (last) + width += stbtt_GetCodepointKernAdvance(font, last, ch); + + /* First get some basic metrics about this character */ + stbtt_GetCodepointHMetrics(font, ch, &advance, &lsb); + + width += advance; + last = ch; + } + + bbox->valid = true; + bbox->x0 = 0; + bbox->y0 = 0; + bbox->x1 = tt_ceil((double)width * met->scale); + bbox->y1 = met->font_size; + + return 0; +} + const char *console_truetype_get_font_size(struct udevice *dev, uint *sizep) { struct console_tt_priv *priv = dev_get_priv(dev); @@ -709,6 +768,7 @@ struct vidconsole_ops console_truetype_ops = { .get_font = console_truetype_get_font, .get_font_size = console_truetype_get_font_size, .select_font = truetype_select_font, + .measure = truetype_measure, }; U_BOOT_DRIVER(vidconsole_truetype) = { diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index 3f89537c47b7..05f930478096 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -596,6 +596,28 @@ int vidconsole_select_font(struct udevice *dev, const char *name, uint size) return ops->select_font(dev, name, size); } +int vidconsole_measure(struct udevice *dev, const char *name, uint size, + const char *text, struct vidconsole_bbox *bbox) +{ + struct vidconsole_priv *priv = dev_get_uclass_priv(dev); + struct vidconsole_ops *ops = vidconsole_get_ops(dev); + int ret; + + if (ops->select_font) { + ret = ops->measure(dev, name, size, text, bbox); + if (ret != -ENOSYS) + return ret; + } + + bbox->valid = true; + bbox->x0 = 0; + bbox->y0 = 0; + bbox->x1 = priv->x_charsize * strlen(text); + bbox->y1 = priv->y_charsize; + + return 0; +} + void vidconsole_push_colour(struct udevice *dev, enum colour_idx fg, enum colour_idx bg, struct vidconsole_colour *old) { diff --git a/include/video_console.h b/include/video_console.h index 81d4c4d874df..2694e44f6ecf 100644 --- a/include/video_console.h +++ b/include/video_console.h @@ -82,6 +82,27 @@ struct vidconsole_colour { u32 colour_bg; }; +/** + * struct vidconsole_bbox - Bounding box of text + * + * This describes the bounding box of something, measured in pixels. The x0/y0 + * pair is inclusive; the x1/y2 pair is exclusive, meaning that it is one pixel + * beyond the extent of the object + * + * @valid: Values are valid (bounding box is known) + * @x0: left x position, in pixels from left side + * @y0: top y position, in pixels from top + * @x1: right x position + 1 + * @y1: botton y position + 1 + */ +struct vidconsole_bbox { + bool valid; + int x0; + int y0; + int x1; + int y1; +}; + /** * struct vidconsole_ops - Video console operations * @@ -189,6 +210,20 @@ struct vidconsole_ops { * Returns: 0 on success, -ENOENT if no such font */ int (*select_font)(struct udevice *dev, const char *name, uint size); + + /** + * measure() - Measure the bounds of some text + * + * @dev: Device to adjust + * @name: Font name to use (NULL to use default) + * @size: Font size to use (0 to use default) + * @text: Text to measure + * @bbox: Returns bounding box of text, assuming it is positioned + * at 0,0 + * Returns: 0 on success, -ENOENT if no such font + */ + int (*measure)(struct udevice *dev, const char *name, uint size, + const char *text, struct vidconsole_bbox *bbox); }; /* Get a pointer to the driver operations for a video console device */ @@ -215,6 +250,19 @@ int vidconsole_get_font(struct udevice *dev, int seq, */ int vidconsole_select_font(struct udevice *dev, const char *name, uint size); +/* + * vidconsole_measure() - Measuring the bounding box of some text + * + * @dev: Console device to use + * @name: Font name, NULL for default + * @size: Font size, ignored if @name is NULL + * @text: Text to measure + * @bbox: Returns nounding box of text + * Returns: 0 if OK, -ve on error + */ +int vidconsole_measure(struct udevice *dev, const char *name, uint size, + const char *text, struct vidconsole_bbox *bbox); + /** * vidconsole_push_colour() - Temporarily change the font colour * From patchwork Thu Jun 1 16:22:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789242 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=J0osaMxM; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBSH2FZbz20QB for ; Fri, 2 Jun 2023 02:30:07 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id EB85586442; Thu, 1 Jun 2023 18:25:48 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="J0osaMxM"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 2D47C86358; Thu, 1 Jun 2023 18:25:18 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x133.google.com (mail-il1-x133.google.com [IPv6:2607:f8b0:4864:20::133]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 863C586381 for ; Thu, 1 Jun 2023 18:25:04 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x133.google.com with SMTP id e9e14a558f8ab-33b22221da6so3652875ab.1 for ; Thu, 01 Jun 2023 09:25:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636686; x=1688228686; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=/4Omd7MCvTwyYZU7DDO1NUPxhn4Ho55V8F48HKYX4ck=; b=J0osaMxM4sK2eVCqxS7kWpT/EdmYvPa3cB1w8c6o20KEKfzuP0BIfbQOECRNB8O29v vCEHd6oMSaIzyZQmHzzIDDB+BG7Mp/GinKTwUbMQuTT53/+55u6ou2Vw2z0HMfNZSjZb Vca9MVTuuqDvlHvqMpb1m9s7iZ3jI1joMZq2Q= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636686; x=1688228686; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=/4Omd7MCvTwyYZU7DDO1NUPxhn4Ho55V8F48HKYX4ck=; b=jfyUEPeuBLjtpyEfcNjCLhbJrUVxq1pb7ofd/YkfzsmFt7piCD6ZrTohaNx5GzmRa1 0HsD28lElI4MUzBrvKJLgTvcVYCQj1hAGTmhNxntdI3X+P0koC2+H+cc9X6sUrPaMFaJ WPTv/D2S+bK3Q0QijHUE6lLwr+uGJA414PmW2ABTwMsyQvUmSClgosyYqfAlaMMOL3fv 9o4fL7kA6LXNHxajELV6F3cBxYJB2C6fPxtNRTCMtlSSWe5FeshhxVw2WkMe2H4QF/W7 4hC7Nz32QHS1pMaraZLtvZgs0TFOKzDVFdhgXVnGHofqEQtjn8dFr09fxwW3CuZzw6e3 DMJQ== X-Gm-Message-State: AC+VfDw3kjASBG9zRu/Wo480oUqISS8OfHmKsBd/Lqo9Ezpx7Zvw4PXF jHblqRdNxCcix47kg7Y2ErYYmWGH7pW7FPDd05o= X-Google-Smtp-Source: ACHHUZ5+JVqeSh5o4udqGvdJPYHKoc5QFEyFPRFM0tJ6/h91olAn3h0TFNSgACeEi+z2DAOXz+2Rzg== X-Received: by 2002:a92:dacd:0:b0:33b:ea2:fe6c with SMTP id o13-20020a92dacd000000b0033b0ea2fe6cmr6557505ilq.24.1685636685913; Thu, 01 Jun 2023 09:24:45 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:45 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 23/40] expo: Allow setting the start of the dynamic-ID range Date: Thu, 1 Jun 2023 10:22:47 -0600 Message-ID: <20230601162404.220488-22-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Provide a way to set this value so that it is easy to separate the statically allocated IDs (generated by the caller) from those generated dynamically by expo itself. Signed-off-by: Simon Glass --- boot/expo.c | 15 +++++++++++++++ boot/scene.c | 10 ---------- doc/develop/expo.rst | 3 +++ include/expo.h | 19 +++++++++++++++++++ 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/boot/expo.c b/boot/expo.c index 8b966b6c793c..be11cfd4e946 100644 --- a/boot/expo.c +++ b/boot/expo.c @@ -56,6 +56,21 @@ void expo_destroy(struct expo *exp) free(exp); } +uint resolve_id(struct expo *exp, uint id) +{ + if (!id) + id = exp->next_id++; + else if (id >= exp->next_id) + exp->next_id = id + 1; + + return id; +} + +void expo_set_dynamic_start(struct expo *exp, uint dyn_start) +{ + exp->next_id = dyn_start; +} + int expo_str(struct expo *exp, const char *name, uint id, const char *str) { struct expo_string *estr; diff --git a/boot/scene.c b/boot/scene.c index 43c978e6ee80..2ac9bfcdbd52 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -18,16 +18,6 @@ #include #include "scene_internal.h" -uint resolve_id(struct expo *exp, uint id) -{ - if (!id) - id = exp->next_id++; - else if (id >= exp->next_id) - exp->next_id = id + 1; - - return id; -} - int scene_new(struct expo *exp, const char *name, uint id, struct scene **scnp) { struct scene *scn; diff --git a/doc/develop/expo.rst b/doc/develop/expo.rst index 32dd7f090307..9565974a28e9 100644 --- a/doc/develop/expo.rst +++ b/doc/develop/expo.rst @@ -85,6 +85,9 @@ or even the IDs of objects. Programmatic creation of many items in a loop can be handled by allocating space in the enum for a maximum number of items, then adding the loop count to the enum values to obtain unique IDs. +Where dynamic IDs are need, use expo_set_dynamic_start() to set the start value, +so that they are allocated above the starting (enum) IDs. + All text strings are stored in a structure attached to the expo, referenced by a text ID. This makes it easier at some point to implement multiple languages or to support Unicode strings. diff --git a/include/expo.h b/include/expo.h index f77ee7085192..b8f5327f2664 100644 --- a/include/expo.h +++ b/include/expo.h @@ -257,6 +257,25 @@ int expo_new(const char *name, void *priv, struct expo **expp); */ void expo_destroy(struct expo *exp); +/** + * expo_set_dynamic_start() - Set the start of the 'dynamic' IDs + * + * It is common for a set of 'static' IDs to be used to refer to objects in the + * expo. These typically use an enum so that they are defined in sequential + * order. + * + * Dynamic IDs (for objects not in the enum) are intended to be used for + * objects to which the code does not need to refer. These are ideally located + * above the static IDs. + * + * Use this function to set the start of the dynamic range, making sure that the + * value is higher than all the statically allocated IDs. + * + * @exp: Expo to update + * @dyn_start: Start ID that expo should use for dynamic allocation + */ +void expo_set_dynamic_start(struct expo *exp, uint dyn_start); + /** * expo_str() - add a new string to an expo * From patchwork Thu Jun 1 16:22:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789235 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=gIHpMEuG; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBQX2Z1hz20QB for ; Fri, 2 Jun 2023 02:28:36 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 4DB918638D; Thu, 1 Jun 2023 18:25:28 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="gIHpMEuG"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 74D6886373; Thu, 1 Jun 2023 18:24:52 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x131.google.com (mail-il1-x131.google.com [IPv6:2607:f8b0:4864:20::131]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 998DE86347 for ; Thu, 1 Jun 2023 18:24:47 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x131.google.com with SMTP id e9e14a558f8ab-33b1e83e1daso3969675ab.0 for ; Thu, 01 Jun 2023 09:24:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636687; x=1688228687; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=N+XtIYeg9r7FNkDuKrwk9/IJV00v+x6TNpOF1rQlOCY=; b=gIHpMEuGflT7njoWeEEuA3qjWHzM+AOirPpcRB/kRiLCHrxPZYmzt1/mwl5SHgDMFY manNC9xgZRp6n/PzlP4HwK7ZsGUFtbDNsI1KdxLo2D5++fwqXr6uP7Rj1wAF6LpZGVYp SQLAwACJW/AXkt15ILfKoeGGCaglnVWeqWUlM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636687; x=1688228687; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=N+XtIYeg9r7FNkDuKrwk9/IJV00v+x6TNpOF1rQlOCY=; b=am+9alZuc03G+ciELP0Kx3spYuj4QX7ycW31sC6gCfikX4EXSdei9bBp49PVAEp2SK jWtn+CTF5GgHLKYEx/UqNHb86ZQlAg/dSa5GbhYtJolkPxhSDvkuzb5y0oGqfsm0XJPj OiRuGr2VHDJlosZC8o3poI+4WmQCiFIEWScyXgg+sO3PQOaCnOnwrP+8zRUh74W8bVww QDwcWKjoqucsobtFOjSSK7CION8rKZ2mLY08khlqGYyrg0NnPa96WEvCdYGJh9axhJsg GHVlCJeJ3tVUmiz+29q70U8qBpv7jfsnwkVCBDo/lQdcVOmHjlQ1JIkpNYFxK3XRAcXW f7Qg== X-Gm-Message-State: AC+VfDzV5wny+Rxi79tPkOjpfEMcuYJSB9b8luKb3uFAQglxuNbvS7Cf ThL2IWtL1LfIgo9lSwk04O1tFubKq/zTzfYeL/A= X-Google-Smtp-Source: ACHHUZ6JhQgw3XKa1rex4rDER32Nt2bYunvHIQ0XLlV1sCar6ufnyJljXUSaP0QTlaMzFjHJwFQZ6Q== X-Received: by 2002:a92:d986:0:b0:328:52d1:6415 with SMTP id r6-20020a92d986000000b0032852d16415mr6538152iln.15.1685636687075; Thu, 01 Jun 2023 09:24:47 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:46 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass , Anatolij Gustschin Subject: [PATCH 24/40] video: Use enum with video_index_to_colour() Date: Thu, 1 Jun 2023 10:22:48 -0600 Message-ID: <20230601162404.220488-23-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Use the provided enum with this function, so it is clearer what should be passed to it. Signed-off-by: Simon Glass --- drivers/video/video-uclass.c | 2 +- include/video.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index 1db049bec004..5bf40e1138f4 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -260,7 +260,7 @@ static const struct vid_rgb colours[VID_COLOUR_COUNT] = { { 0xff, 0xff, 0xff }, /* white */ }; -u32 video_index_to_colour(struct video_priv *priv, unsigned int idx) +u32 video_index_to_colour(struct video_priv *priv, enum colour_idx idx) { switch (priv->bpix) { case VIDEO_BPP16: diff --git a/include/video.h b/include/video.h index dd0d55baa31a..124eb49fab7d 100644 --- a/include/video.h +++ b/include/video.h @@ -163,10 +163,10 @@ enum colour_idx { * VID_COLOR_COUNT. * * @priv private data of the video device (UCLASS_VIDEO) - * @idx color index + * @idx color index (e.g. VID_YELLOW) * Return: color value */ -u32 video_index_to_colour(struct video_priv *priv, unsigned int idx); +u32 video_index_to_colour(struct video_priv *priv, enum colour_idx idx); /** * video_reserve() - Reserve frame-buffer memory for video devices From patchwork Thu Jun 1 16:22:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789245 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=apcCL4qe; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBSp2Mz4z20QJ for ; Fri, 2 Jun 2023 02:30:34 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 8472B865CA; Thu, 1 Jun 2023 18:25:54 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="apcCL4qe"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id B88E286386; Thu, 1 Jun 2023 18:25:20 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x129.google.com (mail-il1-x129.google.com [IPv6:2607:f8b0:4864:20::129]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 89C2D86385 for ; Thu, 1 Jun 2023 18:25:05 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x129.google.com with SMTP id e9e14a558f8ab-33d269dd56bso1806375ab.1 for ; Thu, 01 Jun 2023 09:25:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636688; x=1688228688; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7Ijlu/UfDmKYdpBquWHqt+UMo2fU1dXnUqfyVtt9OWw=; b=apcCL4qecU/oA/7o/cHbT5uI8nYWpCx/imv7XmPDpK2SY4jX0mST08cMjlyo5heQlU RPbCpesgXk1biEU/Xq+7ud2KXF+YZvQKFCi5pTzWPjHp1mQTR9AMPmfqWY/3NAA3e6xM YHWyUJPR5lbQtr5EX2w1HUuCAljVgH2qaQW14= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636688; x=1688228688; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7Ijlu/UfDmKYdpBquWHqt+UMo2fU1dXnUqfyVtt9OWw=; b=CpuKooFCXEnxeYr25CxSegFXj/quvHeJIaRT+wQNlBecndoYmX9mje6oZvqdOJdw+V h3RL8PxcguFyyTcSSzZltnfdCfP/CoGMdsc5h5IdJX42IsXWdF9wJHDxXYA9svCAIvn0 oYMccUG6Y1am6cZ2pclsqVzudeCdqgUc5QOdFz+B8Dvm/SlYChA7X41s9VNGqrJrbkfJ 2VhOIgzP5smubl3Dx/xIhvYw8XcVbePF97+AI6DVbbWA1LWzQkSs814exVwVIPOqspc6 viR+rn+L2mdGHNPfPa9tkP2hyQ1Tg3N6hXNld/cBGcQdNH8yUl9pr5/Kd9HnEV0nuB0q SRIg== X-Gm-Message-State: AC+VfDy+vYPsB8aC9bhQtYDZy/HVBG5SwMcP8mAbnBm/Jehh6M8NMipI M1MHgqkjdscNAhTIU6B3VdKzw+W9V/bgAFtEArk= X-Google-Smtp-Source: ACHHUZ5njrB4WJ38rWgk/wxSBSx/1RZByg7EiQr0YShRMAE65KSMCUt7WPHML06wpJAwzZLhrX7oWA== X-Received: by 2002:a92:cc43:0:b0:338:af0b:f2bd with SMTP id t3-20020a92cc43000000b00338af0bf2bdmr4818662ilq.5.1685636688087; Thu, 01 Jun 2023 09:24:48 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:47 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 25/40] expo: Add width and height to objects Date: Thu, 1 Jun 2023 10:22:49 -0600 Message-ID: <20230601162404.220488-24-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean At present objects only have a position so it is not possible to determine the amount of space they take up on the display. Add width and height properties, using a struct to keep all the dimensions together. For now this is not used. Future work will set up these new properties. Signed-off-by: Simon Glass --- boot/scene.c | 8 ++++---- boot/scene_menu.c | 12 ++++++------ include/expo.h | 21 +++++++++++++++++---- test/boot/expo.c | 32 ++++++++++++++++---------------- 4 files changed, 43 insertions(+), 30 deletions(-) diff --git a/boot/scene.c b/boot/scene.c index 2ac9bfcdbd52..8033d77fb266 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -201,8 +201,8 @@ int scene_obj_set_pos(struct scene *scn, uint id, int x, int y) obj = scene_obj_find(scn, id, SCENEOBJT_NONE); if (!obj) return log_msg_ret("find", -ENOENT); - obj->x = x; - obj->y = y; + obj->dim.x = x; + obj->dim.y = y; return 0; } @@ -272,8 +272,8 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode) struct udevice *cons = text_mode ? NULL : exp->cons; int x, y, ret; - x = obj->x; - y = obj->y; + x = obj->dim.x; + y = obj->dim.y; switch (obj->type) { case SCENEOBJT_NONE: diff --git a/boot/scene_menu.c b/boot/scene_menu.c index 8b04d4403139..eed7565f6a61 100644 --- a/boot/scene_menu.c +++ b/boot/scene_menu.c @@ -49,9 +49,9 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu) int y, cur_y; int ret; - y = menu->obj.y; + y = menu->obj.dim.y; if (menu->title_id) { - ret = scene_obj_set_pos(scn, menu->title_id, menu->obj.x, y); + ret = scene_obj_set_pos(scn, menu->title_id, menu->obj.dim.x, y); if (ret < 0) return log_msg_ret("tit", ret); @@ -89,18 +89,18 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu) * pointer, then the key and the description */ if (item->label_id) { - ret = scene_obj_set_pos(scn, item->label_id, menu->obj.x, + ret = scene_obj_set_pos(scn, item->label_id, menu->obj.dim.x, y); if (ret < 0) return log_msg_ret("nam", ret); } - ret = scene_obj_set_pos(scn, item->key_id, menu->obj.x + 230, + ret = scene_obj_set_pos(scn, item->key_id, menu->obj.dim.x + 230, y); if (ret < 0) return log_msg_ret("key", ret); - ret = scene_obj_set_pos(scn, item->desc_id, menu->obj.x + 280, + ret = scene_obj_set_pos(scn, item->desc_id, menu->obj.dim.x + 280, y); if (ret < 0) return log_msg_ret("des", ret); @@ -134,7 +134,7 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu) * points to */ ret = scene_obj_set_pos(scn, menu->pointer_id, - menu->obj.x + 200, cur_y); + menu->obj.dim.x + 200, cur_y); if (ret < 0) return log_msg_ret("ptr", ret); } diff --git a/include/expo.h b/include/expo.h index b8f5327f2664..5135954ba139 100644 --- a/include/expo.h +++ b/include/expo.h @@ -122,6 +122,21 @@ enum scene_obj_t { SCENEOBJT_MENU, }; +/** + * struct scene_dim - Dimensions of an object + * + * @x: x position, in pixels from left side + * @y: y position, in pixels from top + * @w: width, in pixels + * @h: height, in pixels + */ +struct scene_dim { + int x; + int y; + int w; + int h; +}; + /** * struct scene_obj - information about an object in a scene * @@ -129,8 +144,7 @@ enum scene_obj_t { * @name: Name of the object (allocated) * @id: ID number of the object * @type: Type of this object - * @x: x position, in pixels from left side - * @y: y position, in pixels from top + * @dim: Dimensions for this object * @hide: true if the object should be hidden * @sibling: Node to link this object to its siblings */ @@ -139,8 +153,7 @@ struct scene_obj { char *name; uint id; enum scene_obj_t type; - int x; - int y; + struct scene_dim dim; bool hide; struct list_head sibling; }; diff --git a/test/boot/expo.c b/test/boot/expo.c index 70750d307ffa..10cb7b246f3f 100644 --- a/test/boot/expo.c +++ b/test/boot/expo.c @@ -250,8 +250,8 @@ static int expo_object_attr(struct unit_test_state *uts) ut_assert(id > 0); ut_assertok(scene_obj_set_pos(scn, OBJ_LOGO, 123, 456)); - ut_asserteq(123, img->obj.x); - ut_asserteq(456, img->obj.y); + ut_asserteq(123, img->obj.dim.x); + ut_asserteq(456, img->obj.dim.y); ut_asserteq(-ENOENT, scene_obj_set_pos(scn, OBJ_TEXT2, 0, 0)); @@ -307,8 +307,8 @@ static int expo_object_menu(struct unit_test_state *uts) ut_asserteq(0, menu->pointer_id); ut_assertok(scene_obj_set_pos(scn, OBJ_MENU, 50, 400)); - ut_asserteq(50, menu->obj.x); - ut_asserteq(400, menu->obj.y); + ut_asserteq(50, menu->obj.dim.x); + ut_asserteq(400, menu->obj.dim.y); id = scene_txt_str(scn, "title", OBJ_MENU_TITLE, STR_MENU_TITLE, "Main Menu", &tit); @@ -354,24 +354,24 @@ static int expo_object_menu(struct unit_test_state *uts) ut_asserteq(id, menu->cur_item_id); /* the title should be at the top */ - ut_asserteq(menu->obj.x, tit->obj.x); - ut_asserteq(menu->obj.y, tit->obj.y); + ut_asserteq(menu->obj.dim.x, tit->obj.dim.x); + ut_asserteq(menu->obj.dim.y, tit->obj.dim.y); /* the first item should be next */ - ut_asserteq(menu->obj.x, name1->obj.x); - ut_asserteq(menu->obj.y + 32, name1->obj.y); + ut_asserteq(menu->obj.dim.x, name1->obj.dim.x); + ut_asserteq(menu->obj.dim.y + 32, name1->obj.dim.y); - ut_asserteq(menu->obj.x + 230, key1->obj.x); - ut_asserteq(menu->obj.y + 32, key1->obj.y); + ut_asserteq(menu->obj.dim.x + 230, key1->obj.dim.x); + ut_asserteq(menu->obj.dim.y + 32, key1->obj.dim.y); - ut_asserteq(menu->obj.x + 200, ptr->obj.x); - ut_asserteq(menu->obj.y + 32, ptr->obj.y); + ut_asserteq(menu->obj.dim.x + 200, ptr->obj.dim.x); + ut_asserteq(menu->obj.dim.y + 32, ptr->obj.dim.y); - ut_asserteq(menu->obj.x + 280, desc1->obj.x); - ut_asserteq(menu->obj.y + 32, desc1->obj.y); + ut_asserteq(menu->obj.dim.x + 280, desc1->obj.dim.x); + ut_asserteq(menu->obj.dim.y + 32, desc1->obj.dim.y); - ut_asserteq(-4, prev1->obj.x); - ut_asserteq(menu->obj.y + 32, prev1->obj.y); + ut_asserteq(-4, prev1->obj.dim.x); + ut_asserteq(menu->obj.dim.y + 32, prev1->obj.dim.y); ut_asserteq(false, prev1->obj.hide); expo_destroy(exp); From patchwork Thu Jun 1 16:22:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789236 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=COnVAdjI; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBQm44Tmz20Py for ; Fri, 2 Jun 2023 02:28:48 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 1DF2E863AF; Thu, 1 Jun 2023 18:25:31 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="COnVAdjI"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id C3FDE8637C; Thu, 1 Jun 2023 18:24:55 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x12e.google.com (mail-il1-x12e.google.com [IPv6:2607:f8b0:4864:20::12e]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 7CB878632A for ; Thu, 1 Jun 2023 18:24:49 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x12e.google.com with SMTP id e9e14a558f8ab-33bbc91dcb7so4222815ab.3 for ; Thu, 01 Jun 2023 09:24:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636689; x=1688228689; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=3Zuv9xE5x8W5FYKc8NzyVyCqGA4o+LCoEc9+XcttuxY=; b=COnVAdjItTDectkLJC8W1/23ita9mqaoKs2crFXdYn5Nz46xNQ5ldBJvEMW0U5Xcd5 ybRTZYTvfwjCKFOTAeOkxuY7o1N/S5z9mJ3h4qZAh+CXJ8PQu/wo/J6ZX5RllQgo+kIr OI7PiKjX/hhx4moHtyxCLQr1Byvr9X/itV+9Y= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636689; x=1688228689; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=3Zuv9xE5x8W5FYKc8NzyVyCqGA4o+LCoEc9+XcttuxY=; b=DGPscKL4Ona/m6u3ytj/XZ9cw4dpimrGAEtd2CLcglgXi3qtMxOaqutuLpX68sTtzF Ouf8XnLYBQOrn+RdlwV/t/WrushRntH2tNmfKvfNpkDsXEr0+vMwV3WCIXDTCyYbvqTq mwgxf58QXKW2y3KIUfDYYUSiUvtW5Ik2FWM6MWX439H8E8OOQuHillNwtfCFKeQ33Kui NxNdpaokKwhZzUYVg4FaD4HIj1rLjbGMNSqzKAoIcTpyKy4a1OdPwtRxkjqG5zfoSxVz z0fw2wrOEkh86bDXsvfH7laWyQAURh4dzqEJFfO2dRfld9yzRgUghq1iR10ixpnR13ww CUvQ== X-Gm-Message-State: AC+VfDxnTl4fEVVq+515yHCb1A9vo4iqA1anRObHo2jvBeeZ3Gts7XDb G3328NgNcWagbWCjZE4ZO62k2Gjj2SPYGlFiuLo= X-Google-Smtp-Source: ACHHUZ42HJiLTVvcTI3WglphGfvmiUkgKIAfqlAT0fJ6dYOee3qbKwokyZKIv0yT8U6bkKUaDO+GCA== X-Received: by 2002:a92:d986:0:b0:33a:a518:653f with SMTP id r6-20020a92d986000000b0033aa518653fmr7120018iln.15.1685636688957; Thu, 01 Jun 2023 09:24:48 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:48 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 26/40] expo: Use flags for objects Date: Thu, 1 Jun 2023 10:22:50 -0600 Message-ID: <20230601162404.220488-25-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean We currently have just a 'hide' property for each object. In preparation for adding more properties, convert the struct to use a flags value, instead of individual booleans. This is more extensible. Signed-off-by: Simon Glass --- boot/scene.c | 17 +++++++++++++++-- boot/scene_internal.h | 11 +++++++++++ include/expo.h | 13 +++++++++++-- test/boot/expo.c | 6 +++--- 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/boot/scene.c b/boot/scene.c index 8033d77fb266..dd1472d4f9aa 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -208,13 +208,26 @@ int scene_obj_set_pos(struct scene *scn, uint id, int x, int y) } int scene_obj_set_hide(struct scene *scn, uint id, bool hide) +{ + int ret; + + ret = scene_obj_flag_clrset(scn, id, SCENEOF_HIDE, + hide ? SCENEOF_HIDE : 0); + if (ret) + return log_msg_ret("flg", ret); + + return 0; +} + +int scene_obj_flag_clrset(struct scene *scn, uint id, uint clr, uint set) { struct scene_obj *obj; obj = scene_obj_find(scn, id, SCENEOBJT_NONE); if (!obj) return log_msg_ret("find", -ENOENT); - obj->hide = hide; + obj->flags &= ~clr; + obj->flags |= set; return 0; } @@ -358,7 +371,7 @@ int scene_render(struct scene *scn) int ret; list_for_each_entry(obj, &scn->obj_head, sibling) { - if (!obj->hide) { + if (!(obj->flags & SCENEOF_HIDE)) { ret = scene_obj_render(obj, exp->text_mode); if (ret && ret != -ENOTSUPP) return log_msg_ret("ren", ret); diff --git a/boot/scene_internal.h b/boot/scene_internal.h index 9f173dd749f0..24a2ba6a6a3d 100644 --- a/boot/scene_internal.h +++ b/boot/scene_internal.h @@ -54,6 +54,17 @@ void *scene_obj_find(struct scene *scn, uint id, enum scene_obj_t type); int scene_obj_add(struct scene *scn, const char *name, uint id, enum scene_obj_t type, uint size, struct scene_obj **objp); +/** + * scene_obj_flag_clrset() - Adjust object flags + * + * @scn: Scene to update + * @id: ID of object to update + * @clr: Bits to clear in the object's flags + * @set: Bits to set in the object's flags + * Returns 0 if OK, -ENOENT if the object was not found + */ +int scene_obj_flag_clrset(struct scene *scn, uint id, uint clr, uint set); + /** * scene_menu_arrange() - Set the position of things in the menu * diff --git a/include/expo.h b/include/expo.h index 5135954ba139..b6777cebcbec 100644 --- a/include/expo.h +++ b/include/expo.h @@ -137,6 +137,15 @@ struct scene_dim { int h; }; +/** + * enum scene_obj_flags_t - flags for objects + * + * @SCENEOF_HIDE: object should be hidden + */ +enum scene_obj_flags_t { + SCENEOF_HIDE = 1 << 0, +}; + /** * struct scene_obj - information about an object in a scene * @@ -145,7 +154,7 @@ struct scene_dim { * @id: ID number of the object * @type: Type of this object * @dim: Dimensions for this object - * @hide: true if the object should be hidden + * @flags: Flags for this object * @sibling: Node to link this object to its siblings */ struct scene_obj { @@ -154,7 +163,7 @@ struct scene_obj { uint id; enum scene_obj_t type; struct scene_dim dim; - bool hide; + int flags; struct list_head sibling; }; diff --git a/test/boot/expo.c b/test/boot/expo.c index 10cb7b246f3f..5088776f7bd5 100644 --- a/test/boot/expo.c +++ b/test/boot/expo.c @@ -372,7 +372,7 @@ static int expo_object_menu(struct unit_test_state *uts) ut_asserteq(-4, prev1->obj.dim.x); ut_asserteq(menu->obj.dim.y + 32, prev1->obj.dim.y); - ut_asserteq(false, prev1->obj.hide); + ut_asserteq(false, prev1->obj.flags & SCENEOF_HIDE); expo_destroy(exp); @@ -488,10 +488,10 @@ static int expo_render_image(struct unit_test_state *uts) /* make sure only the preview for the second item is shown */ obj = scene_obj_find(scn, ITEM1_PREVIEW, SCENEOBJT_NONE); - ut_asserteq(true, obj->hide); + ut_asserteq(true, obj->flags & SCENEOF_HIDE); obj = scene_obj_find(scn, ITEM2_PREVIEW, SCENEOBJT_NONE); - ut_asserteq(false, obj->hide); + ut_asserteq(false, obj->flags & SCENEOF_HIDE); /* select it */ ut_assertok(expo_send_key(exp, BKEY_SELECT)); From patchwork Thu Jun 1 16:22:51 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789248 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=CTJBVdCJ; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBTZ1P8Sz20QH for ; Fri, 2 Jun 2023 02:31:14 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 8A64E865CE; Thu, 1 Jun 2023 18:26:07 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="CTJBVdCJ"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id B276086345; Thu, 1 Jun 2023 18:25:22 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x134.google.com (mail-il1-x134.google.com [IPv6:2607:f8b0:4864:20::134]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 15AD586393 for ; Thu, 1 Jun 2023 18:25:06 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x134.google.com with SMTP id e9e14a558f8ab-33b36a9fdf8so3636045ab.2 for ; Thu, 01 Jun 2023 09:25:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636690; x=1688228690; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=HrzmjzW96RBA1t0rWzhi1Qx+9OwUAifeJKc2jexfcn4=; b=CTJBVdCJ3oukDRwhMJOck9qYPu7/8YFPBcGI7LPSDQAWyI6ukepUMvOgS1IeHI9YwY gVnos1kP63dGSy0xgUblGr8ccSyXZpHFtkgW4giIam/uQM8G7zD9zhvlApXMakpc73XT 0Kri7t/f3KB7E4f375p3z0jKeNJjilLvNJEho= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636690; x=1688228690; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=HrzmjzW96RBA1t0rWzhi1Qx+9OwUAifeJKc2jexfcn4=; b=R3cTzDeGaGiTgY/usAhDSbOD1HkkMgOWqcrPB/mYnCLa+U15L2mn9QAD3H6Gsblekb GuIVMK9Zc5x6FkCKPlJJIHpxEV67pDHn2gtD33Syee2tnVkkh6HLxdjXvRd/EyG58FAg QHV+Rczb59CSNwTqKsNK3d7am2gPTf3vREAZBKjjUNPA0G3T9rrvHZAFLnDMtU4iiQCV k1+QPtaDh5GJN2dJJDAdAX9Z2S4dQ4hYPOhxhansuL0xHj5vMoEALtW9HL86D/eMHYtp BlEFYhTYMfgZ+P9KGCOMUDCRXBHO/olTbMrdQNdA4Qzk+KiSx0bojqSF9M44XdMfCMch NQog== X-Gm-Message-State: AC+VfDyFUR4izLdg4iuNpZJn4Pi9TOLXrQC35pBRapQa53/PxZiJmSWe qwijaLKANNJY+4mqJ88VoRYSJvjbbCan3VimtJI= X-Google-Smtp-Source: ACHHUZ48Pi3l7WGal8Iza2TlpU9RdCnfGIiPoKEkaew+OrGGt0ylWQb0e6MON2gJ/xijhD1gw1BWoQ== X-Received: by 2002:a92:d34a:0:b0:32b:50d1:3403 with SMTP id a10-20020a92d34a000000b0032b50d13403mr6700850ilh.7.1685636689999; Thu, 01 Jun 2023 09:24:49 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:49 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 27/40] expo: Calculate text bounding-box correctly Date: Thu, 1 Jun 2023 10:22:51 -0600 Message-ID: <20230601162404.220488-26-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Rather than estimating, measure the text accurately, using the new vidconsole feature. This allows accurate placement of objects. Signed-off-by: Simon Glass --- boot/scene.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/boot/scene.c b/boot/scene.c index dd1472d4f9aa..981a18b3ba1c 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -257,16 +257,30 @@ int scene_obj_get_hw(struct scene *scn, uint id, int *widthp) case SCENEOBJT_TEXT: { struct scene_obj_txt *txt = (struct scene_obj_txt *)obj; struct expo *exp = scn->expo; + struct vidconsole_bbox bbox; + const char *str; + int len, ret; + str = expo_get_str(exp, txt->str_id); + if (!str) + return log_msg_ret("str", -ENOENT); + len = strlen(str); + + /* if there is no console, make it up */ + if (!exp->cons) { + if (widthp) + *widthp = 8 * len; + return 16; + } + + ret = vidconsole_measure(scn->expo->cons, txt->font_name, + txt->font_size, str, &bbox); + if (ret) + return log_msg_ret("mea", ret); if (widthp) - *widthp = 16; /* fake value for now */ - if (txt->font_size) - return txt->font_size; - if (exp->display) - return video_default_font_height(exp->display); - - /* use a sensible default */ - return 16; + *widthp = bbox.x1; + + return bbox.y1; } } From patchwork Thu Jun 1 16:22:52 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789246 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=DNcIyC0A; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBT33XQ6z20QH for ; Fri, 2 Jun 2023 02:30:47 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 1DA2A865D0; Thu, 1 Jun 2023 18:25:57 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="DNcIyC0A"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id E801C863BE; Thu, 1 Jun 2023 18:25:20 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x130.google.com (mail-il1-x130.google.com [IPv6:2607:f8b0:4864:20::130]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 84C868638A for ; Thu, 1 Jun 2023 18:25:06 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x130.google.com with SMTP id e9e14a558f8ab-33be5dbb90cso3673165ab.0 for ; Thu, 01 Jun 2023 09:25:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636691; x=1688228691; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=LtBkwmHDdHxCuESeCA7ABZeuBHwJRUg4axlpaXOtp3w=; b=DNcIyC0AaCcMuGbWRqkWLQx0EJ8FKcm8VPBL51pWHnz+rPYBFpRM23UVA/RxGcRdky Xr+caeMuc02suskHiMaavSw8jaf8WJZs+7MrUY96vL1MCj5nSdbiX3UXQVPp81tzqdCK GNDvyB0j1Yt7tCRE7UYOFD0kgMyDMrlS33LV0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636691; x=1688228691; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=LtBkwmHDdHxCuESeCA7ABZeuBHwJRUg4axlpaXOtp3w=; b=AWYiafJ8+DyRtTOQ4vnVI+dka31Y92KlxdaRB2m0qDM35AZ3bRpYXqYwAqYO3c1Ax0 ct4uws+CM6GVV5IWSBfYi18n65WIsoxVZWk1X//xBrXtGXUk9ZL6TZbw9k932ZgzVxAG pVmCpST9pJXvMcgko4aLfWuhS/VMmWwYomnQGKAWvZ/3BSNcV1EZGwcpflDrShizjeRp HVjfaENeXBjrtKANdAeJEdRcN6EQYuT+72bn86deDVPOtOjK7vCaZojmW1PME1c3Q5jx GFmGAQkNKkx5U4h1v+/NvWaAqAIFKVcq/+Q0J2XjTv2vW+H0ZrPQEpwuT0ed3lEijW6H lOTQ== X-Gm-Message-State: AC+VfDzaBL/EarOFe55RilS41sZ+7fwLTC45y/lwNGVG9v5GGTVWO9Mx VHykYKf6AzRE20R4oUNyFiPBYyo9HUE4vFX8oCY= X-Google-Smtp-Source: ACHHUZ56WOJ6WWdoA+I1L7NNrwZ5j8waRg5AWe3EGOXDF3v+SI5sUlQqyihUnkBe+5lSj4aWNOaYgw== X-Received: by 2002:a92:cb05:0:b0:331:7c4f:54ec with SMTP id s5-20020a92cb05000000b003317c4f54ecmr4733385ilo.30.1685636690854; Thu, 01 Jun 2023 09:24:50 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:50 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 28/40] expo: Set up the width and height of objects Date: Thu, 1 Jun 2023 10:22:52 -0600 Message-ID: <20230601162404.220488-27-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Provide a way to set the full dimensions of objects, i.e. including the width and height. For menus, calculate the bounding box of all objects in the menu. Set all labels to be the same size, so that highlighting works correct, once implemented. Signed-off-by: Simon Glass --- boot/expo.c | 24 +++++++++++++ boot/scene.c | 52 ++++++++++++++++++++++++++++ boot/scene_internal.h | 21 ++++++++++++ boot/scene_menu.c | 79 +++++++++++++++++++++++++++++++++++++++++++ doc/develop/expo.rst | 2 -- include/expo.h | 21 ++++++++++++ test/boot/expo.c | 42 +++++++++++++++++++++++ 7 files changed, 239 insertions(+), 2 deletions(-) diff --git a/boot/expo.c b/boot/expo.c index be11cfd4e946..67cae3c7e28d 100644 --- a/boot/expo.c +++ b/boot/expo.c @@ -114,6 +114,30 @@ int expo_set_display(struct expo *exp, struct udevice *dev) return 0; } +int expo_calc_dims(struct expo *exp) +{ + struct scene *scn; + int ret; + + if (!exp->cons) + return log_msg_ret("dim", -ENOTSUPP); + + list_for_each_entry(scn, &exp->scene_head, sibling) { + /* + * Do the menus last so that all the menus' text objects + * are dimensioned + */ + ret = scene_calc_dims(scn, false); + if (ret) + return log_msg_ret("scn", ret); + ret = scene_calc_dims(scn, true); + if (ret) + return log_msg_ret("scn", ret); + } + + return 0; +} + void expo_set_text_mode(struct expo *exp, bool text_mode) { exp->text_mode = text_mode; diff --git a/boot/scene.c b/boot/scene.c index 981a18b3ba1c..6d5e3c1f03dd 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -207,6 +207,19 @@ int scene_obj_set_pos(struct scene *scn, uint id, int x, int y) return 0; } +int scene_obj_set_size(struct scene *scn, uint id, int w, int h) +{ + struct scene_obj *obj; + + obj = scene_obj_find(scn, id, SCENEOBJT_NONE); + if (!obj) + return log_msg_ret("find", -ENOENT); + obj->dim.w = w; + obj->dim.h = h; + + return 0; +} + int scene_obj_set_hide(struct scene *scn, uint id, bool hide) { int ret; @@ -414,3 +427,42 @@ int scene_send_key(struct scene *scn, int key, struct expo_action *event) return 0; } + +int scene_calc_dims(struct scene *scn, bool do_menus) +{ + struct scene_obj *obj; + int ret; + + list_for_each_entry(obj, &scn->obj_head, sibling) { + switch (obj->type) { + case SCENEOBJT_NONE: + case SCENEOBJT_TEXT: + case SCENEOBJT_IMAGE: { + int width; + + if (!do_menus) { + ret = scene_obj_get_hw(scn, obj->id, &width); + if (ret < 0) + return log_msg_ret("get", ret); + obj->dim.w = width; + obj->dim.h = ret; + } + break; + } + case SCENEOBJT_MENU: { + struct scene_obj_menu *menu; + + if (do_menus) { + menu = (struct scene_obj_menu *)obj; + + ret = scene_menu_calc_dims(menu); + if (ret) + return log_msg_ret("men", ret); + } + break; + } + } + } + + return 0; +} diff --git a/boot/scene_internal.h b/boot/scene_internal.h index 24a2ba6a6a3d..00085a2f55d3 100644 --- a/boot/scene_internal.h +++ b/boot/scene_internal.h @@ -65,6 +65,17 @@ int scene_obj_add(struct scene *scn, const char *name, uint id, */ int scene_obj_flag_clrset(struct scene *scn, uint id, uint clr, uint set); +/** + * scene_calc_dims() - Calculate the dimensions of the scene objects + * + * Updates the width and height of all objects based on their contents + * + * @scn: Scene to update + * @do_menus: true to calculate only menus, false to calculate everything else + * Returns 0 if OK, -ENOTSUPP if there is no graphical console + */ +int scene_calc_dims(struct scene *scn, bool do_menus); + /** * scene_menu_arrange() - Set the position of things in the menu * @@ -133,4 +144,14 @@ int scene_render(struct scene *scn); */ int scene_send_key(struct scene *scn, int key, struct expo_action *event); +/** + * scene_menu_calc_dims() - Calculate the dimensions of a menu + * + * Updates the width and height of the menu based on its contents + * + * @menu: Menu to update + * Returns 0 if OK, -ENOTSUPP if there is no graphical console + */ +int scene_menu_calc_dims(struct scene_obj_menu *menu); + #endif /* __SCENE_INTERNAL_H */ diff --git a/boot/scene_menu.c b/boot/scene_menu.c index eed7565f6a61..fa79cecdbd93 100644 --- a/boot/scene_menu.c +++ b/boot/scene_menu.c @@ -43,6 +43,85 @@ static void menu_point_to_item(struct scene_obj_menu *menu, uint item_id) menu->cur_item_id = item_id; } +static int scene_bbox_union(struct scene *scn, uint id, + struct vidconsole_bbox *bbox) +{ + struct scene_obj *obj; + + if (!id) + return 0; + obj = scene_obj_find(scn, id, SCENEOBJT_NONE); + if (!obj) + return log_msg_ret("obj", -ENOENT); + if (bbox->valid) { + bbox->x0 = min(bbox->x0, obj->dim.x); + bbox->y0 = min(bbox->y0, obj->dim.y); + bbox->x1 = max(bbox->x1, obj->dim.x + obj->dim.w); + bbox->y1 = max(bbox->y1, obj->dim.y + obj->dim.h); + } else { + bbox->x0 = obj->dim.x; + bbox->y0 = obj->dim.y; + bbox->x1 = obj->dim.x + obj->dim.w; + bbox->y1 = obj->dim.y + obj->dim.h; + bbox->valid = true; + } + + return 0; +} + +/** + * scene_menu_calc_bbox() - Calculate bounding boxes for the menu + * + * @menu: Menu to process + * @bbox: Returns bounding box of menu including prompts + * @label_bbox: Returns bounding box of labels + */ +static void scene_menu_calc_bbox(struct scene_obj_menu *menu, + struct vidconsole_bbox *bbox, + struct vidconsole_bbox *label_bbox) +{ + const struct scene_menitem *item; + + bbox->valid = false; + scene_bbox_union(menu->obj.scene, menu->title_id, bbox); + + label_bbox->valid = false; + + list_for_each_entry(item, &menu->item_head, sibling) { + scene_bbox_union(menu->obj.scene, item->label_id, bbox); + scene_bbox_union(menu->obj.scene, item->key_id, bbox); + scene_bbox_union(menu->obj.scene, item->desc_id, bbox); + scene_bbox_union(menu->obj.scene, item->preview_id, bbox); + + /* Get the bounding box of all labels */ + scene_bbox_union(menu->obj.scene, item->label_id, label_bbox); + } +} + +int scene_menu_calc_dims(struct scene_obj_menu *menu) +{ + struct vidconsole_bbox bbox, label_bbox; + const struct scene_menitem *item; + + scene_menu_calc_bbox(menu, &bbox, &label_bbox); + + /* Make all labels the same size */ + if (label_bbox.valid) { + list_for_each_entry(item, &menu->item_head, sibling) { + scene_obj_set_size(menu->obj.scene, item->label_id, + label_bbox.x1 - label_bbox.x0, + label_bbox.y1 - label_bbox.y0); + } + } + + if (bbox.valid) { + menu->obj.dim.w = bbox.x1 - bbox.x0; + menu->obj.dim.h = bbox.y1 - bbox.y0; + } + + return 0; +} + int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu) { struct scene_menitem *item; diff --git a/doc/develop/expo.rst b/doc/develop/expo.rst index 9565974a28e9..54861b93acf8 100644 --- a/doc/develop/expo.rst +++ b/doc/develop/expo.rst @@ -182,8 +182,6 @@ Some ideas for future work: - Add a Kconfig option to drop the names to save code / data space - Add a Kconfig option to disable vidconsole support to save code / data space - Support both graphical and text menus at the same time on different devices -- Implement proper measurement of object bounding boxes, to permit more exact - layout. This would tidy up the layout when Truetype is not used - Support unicode - Support curses for proper serial-terminal menus diff --git a/include/expo.h b/include/expo.h index b6777cebcbec..6c45c403cf79 100644 --- a/include/expo.h +++ b/include/expo.h @@ -327,6 +327,16 @@ const char *expo_get_str(struct expo *exp, uint id); */ int expo_set_display(struct expo *exp, struct udevice *dev); +/** + * expo_calc_dims() - Calculate the dimensions of the objects + * + * Updates the width and height of all objects based on their contents + * + * @exp: Expo to update + * Returns 0 if OK, -ENOTSUPP if there is no graphical console + */ +int expo_calc_dims(struct expo *exp); + /** * expo_set_scene_id() - Set the current scene ID * @@ -468,6 +478,17 @@ int scene_txt_set_font(struct scene *scn, uint id, const char *font_name, */ int scene_obj_set_pos(struct scene *scn, uint id, int x, int y); +/** + * scene_obj_set_size() - Set the size of an object + * + * @scn: Scene to update + * @id: ID of object to update + * @w: width in pixels + * @h: height in pixels + * Returns: 0 if OK, -ENOENT if @id is invalid + */ +int scene_obj_set_size(struct scene *scn, uint id, int w, int h); + /** * scene_obj_set_hide() - Set whether an object is hidden * diff --git a/test/boot/expo.c b/test/boot/expo.c index 5088776f7bd5..493d050baf87 100644 --- a/test/boot/expo.c +++ b/test/boot/expo.c @@ -473,6 +473,48 @@ static int expo_render_image(struct unit_test_state *uts) /* render without a scene */ ut_asserteq(-ECHILD, expo_render(exp)); + ut_assertok(expo_calc_dims(exp)); + ut_assertok(scene_arrange(scn)); + + /* check dimensions of text */ + obj = scene_obj_find(scn, OBJ_TEXT, SCENEOBJT_NONE); + ut_assertnonnull(obj); + ut_asserteq(400, obj->dim.x); + ut_asserteq(100, obj->dim.y); + ut_asserteq(126, obj->dim.w); + ut_asserteq(40, obj->dim.h); + + /* check dimensions of image */ + obj = scene_obj_find(scn, OBJ_LOGO, SCENEOBJT_NONE); + ut_assertnonnull(obj); + ut_asserteq(50, obj->dim.x); + ut_asserteq(20, obj->dim.y); + ut_asserteq(160, obj->dim.w); + ut_asserteq(160, obj->dim.h); + + /* check dimensions of menu labels - both should be the same width */ + obj = scene_obj_find(scn, ITEM1_LABEL, SCENEOBJT_NONE); + ut_assertnonnull(obj); + ut_asserteq(50, obj->dim.x); + ut_asserteq(436, obj->dim.y); + ut_asserteq(29, obj->dim.w); + ut_asserteq(18, obj->dim.h); + + obj = scene_obj_find(scn, ITEM2_LABEL, SCENEOBJT_NONE); + ut_assertnonnull(obj); + ut_asserteq(50, obj->dim.x); + ut_asserteq(454, obj->dim.y); + ut_asserteq(29, obj->dim.w); + ut_asserteq(18, obj->dim.h); + + /* check dimensions of menu */ + obj = scene_obj_find(scn, OBJ_MENU, SCENEOBJT_NONE); + ut_assertnonnull(obj); + ut_asserteq(50, obj->dim.x); + ut_asserteq(400, obj->dim.y); + ut_asserteq(160, obj->dim.w); + ut_asserteq(160, obj->dim.h); + /* render it */ expo_set_scene_id(exp, SCENE1); ut_assertok(expo_render(exp)); From patchwork Thu Jun 1 16:22:53 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789243 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=k92xFod2; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBSX5tSVz20QH for ; Fri, 2 Jun 2023 02:30:20 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 99C1C865C1; Thu, 1 Jun 2023 18:25:51 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="k92xFod2"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 684C2863A3; Thu, 1 Jun 2023 18:25:20 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x134.google.com (mail-il1-x134.google.com [IPv6:2607:f8b0:4864:20::134]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 90D358639C for ; Thu, 1 Jun 2023 18:25:08 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x134.google.com with SMTP id e9e14a558f8ab-33b3fa03738so4157765ab.1 for ; Thu, 01 Jun 2023 09:25:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636692; x=1688228692; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=r5LA6coaNhlImgImG7OxhCfSJeLhNiKlxD4dJ9g0GSs=; b=k92xFod2mKS89tr+8ZjavVlTFtHINeUbtXwbHWUkrmMgqldWYqULUICkoLH1+zo9vl PlDM+MiFVKLUrxuQD2iwENPfsLjeQx7Q/cQFKz0xjlweUBP/mFoEIgrkmGm5FvEE2Nw3 IJCDBPLKlDjUXWMUL0QndkJ5dRCu+SXFDlr1s= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636692; x=1688228692; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=r5LA6coaNhlImgImG7OxhCfSJeLhNiKlxD4dJ9g0GSs=; b=EM2GAse7gOSFOfC3zklEX1puJk5ctXtio7zLO51Ur9NvvNwKOGw/2Olu1kDr2r0Bte LxGxsXMcZ13BZHJgxXlDm3iQgWHBwCG1YbKQM1j9HfeYPAfDSs303CHu1tS1Rpz0z59M G9WmbiNqKfDI/batWQg028RInKkHDuPNBoRYK9az1qNH3rgWX8+J1WU5+yK8/Ig/HU+L GcHXFl6/3v2VBWUo3j+RQRhN+hosIR97vUJ4wcjCkvsmBAbf23uZTIYhVYOTqk5AkRFe 9Rg/rfMOOY1tUPu9TF1V8Ssw3aI7zYWe4asls+yZLmUuG/8Pm9jMDnKIZPsimEiAz2ON 4tDg== X-Gm-Message-State: AC+VfDypvhPbs0fxeNy9dkhsEvjAEQ9TmbaVqD839uE2BAQt791zMGWo la1sOfdHAb3niIF4cZEd5IUTMf2bXxbXUmnidk4= X-Google-Smtp-Source: ACHHUZ779MlLgTGYJgTuX702MZ8P6+Hhnk1xDolIUtAzrckMAdcsU383Q8MeDofazN+N6kAHcWpKdg== X-Received: by 2002:a92:cb05:0:b0:337:a0d8:cdf9 with SMTP id s5-20020a92cb05000000b00337a0d8cdf9mr6334072ilo.28.1685636691925; Thu, 01 Jun 2023 09:24:51 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:51 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 29/40] expo: Support simple themes Date: Thu, 1 Jun 2023 10:22:53 -0600 Message-ID: <20230601162404.220488-28-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean It is a pain to manually set the fonts of all objects to be consistent. Some spacing settings are also better set globally than by manually positioning each object. Add a 'theme' to the expo, to hold this information. For now it includes only the font size. Signed-off-by: Simon Glass --- boot/expo.c | 20 ++++++++++++++++++++ boot/scene.c | 28 ++++++++++++++++++++++++++++ boot/scene_internal.h | 9 +++++++++ doc/develop/expo.rst | 9 +++++++-- include/expo.h | 24 ++++++++++++++++++++++++ test/boot/expo.c | 8 +++++++- 6 files changed, 95 insertions(+), 3 deletions(-) diff --git a/boot/expo.c b/boot/expo.c index 67cae3c7e28d..d5e935966bfd 100644 --- a/boot/expo.c +++ b/boot/expo.c @@ -231,3 +231,23 @@ int expo_action_get(struct expo *exp, struct expo_action *act) return act->type == EXPOACT_NONE ? -EAGAIN : 0; } + +int expo_apply_theme(struct expo *exp, ofnode node) +{ + struct scene *scn; + struct expo_theme *theme = &exp->theme; + int ret; + + log_debug("Applying theme %s\n", ofnode_get_name(node)); + + memset(theme, '\0', sizeof(struct expo_theme)); + ofnode_read_u32(node, "font-size", &theme->font_size); + + list_for_each_entry(scn, &exp->scene_head, sibling) { + ret = scene_apply_theme(scn, theme); + if (ret) + return log_msg_ret("app", ret); + } + + return 0; +} diff --git a/boot/scene.c b/boot/scene.c index 6d5e3c1f03dd..4dbe12a2b740 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -466,3 +466,31 @@ int scene_calc_dims(struct scene *scn, bool do_menus) return 0; } + +int scene_apply_theme(struct scene *scn, struct expo_theme *theme) +{ + struct scene_obj *obj; + int ret; + + /* Avoid error-checking optional items */ + scene_txt_set_font(scn, scn->title_id, NULL, theme->font_size); + + list_for_each_entry(obj, &scn->obj_head, sibling) { + switch (obj->type) { + case SCENEOBJT_NONE: + case SCENEOBJT_IMAGE: + case SCENEOBJT_MENU: + break; + case SCENEOBJT_TEXT: + scene_txt_set_font(scn, obj->id, NULL, + theme->font_size); + break; + } + } + + ret = scene_arrange(scn); + if (ret) + return log_msg_ret("arr", ret); + + return 0; +} diff --git a/boot/scene_internal.h b/boot/scene_internal.h index 00085a2f55d3..3387a90761ab 100644 --- a/boot/scene_internal.h +++ b/boot/scene_internal.h @@ -89,6 +89,15 @@ int scene_calc_dims(struct scene *scn, bool do_menus); */ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu); +/** + * scene_apply_theme() - Apply a theme to a scene + * + * @scn: Scene to update + * @theme: Theme to apply + * Returns: 0 if OK, -ve on error + */ +int scene_apply_theme(struct scene *scn, struct expo_theme *theme); + /** * scene_menu_send_key() - Send a key to a menu for processing * diff --git a/doc/develop/expo.rst b/doc/develop/expo.rst index 54861b93acf8..2f4882899b6d 100644 --- a/doc/develop/expo.rst +++ b/doc/develop/expo.rst @@ -155,8 +155,13 @@ such as scanning devices for more bootflows. Themes ------ -Expo does not itself support themes. The bootflow_menu implement supposed a -basic theme, applying font sizes to the various text objects in the expo. +Expo supports simple themes, for setting the font size, for example. Use the +expo_apply_theme() function to load a theme, passing a node with the required +properties: + +font-size + Font size to use for all text (type: u32) + API documentation ----------------- diff --git a/include/expo.h b/include/expo.h index 6c45c403cf79..ea8f38913d8e 100644 --- a/include/expo.h +++ b/include/expo.h @@ -7,6 +7,7 @@ #ifndef __SCENE_H #define __SCENE_H +#include #include struct udevice; @@ -42,6 +43,19 @@ struct expo_action { }; }; +/** + * struct expo_theme - theme for the expo + * + * @font_size: Default font size for all text + * @menu_inset: Inset width (on each side and top/bottom) for menu items + * @menuitem_gap_y: Gap between menu items in pixels + */ +struct expo_theme { + u32 font_size; + u32 menu_inset; + u32 menuitem_gap_y; +}; + /** * struct expo - information about an expo * @@ -57,6 +71,7 @@ struct expo_action { * type set to EXPOACT_NONE if there is no action * @text_mode: true to use text mode for the menu (no vidconsole) * @priv: Private data for the controller + * @theme: Information about fonts styles, etc. * @scene_head: List of scenes * @str_head: list of strings */ @@ -69,6 +84,7 @@ struct expo { struct expo_action action; bool text_mode; void *priv; + struct expo_theme theme; struct list_head scene_head; struct list_head str_head; }; @@ -583,4 +599,12 @@ int expo_send_key(struct expo *exp, int key); */ int expo_action_get(struct expo *exp, struct expo_action *act); +/** + * expo_apply_theme() - Apply a theme to an expo + * + * @exp: Expo to update + * @node: Node containing the theme + */ +int expo_apply_theme(struct expo *exp, ofnode node); + #endif /*__SCENE_H */ diff --git a/test/boot/expo.c b/test/boot/expo.c index 493d050baf87..c0ef03b59112 100644 --- a/test/boot/expo.c +++ b/test/boot/expo.c @@ -226,7 +226,7 @@ static int expo_object(struct unit_test_state *uts) } BOOTSTD_TEST(expo_object, UT_TESTF_DM | UT_TESTF_SCAN_FDT); -/* Check setting object attributes */ +/* Check setting object attributes and using themes */ static int expo_object_attr(struct unit_test_state *uts) { struct scene_obj_menu *menu; @@ -236,6 +236,7 @@ static int expo_object_attr(struct unit_test_state *uts) struct expo *exp; ulong start_mem; char name[100]; + ofnode node; char *data; int id; @@ -273,6 +274,11 @@ static int expo_object_attr(struct unit_test_state *uts) ut_asserteq(-ENOENT, scene_menu_set_title(scn, OBJ_TEXT2, OBJ_TEXT)); ut_asserteq(-EINVAL, scene_menu_set_title(scn, OBJ_MENU, OBJ_TEXT2)); + node = ofnode_path("/bootstd/theme"); + ut_assert(ofnode_valid(node)); + ut_assertok(expo_apply_theme(exp, node)); + ut_asserteq(30, txt->font_size); + expo_destroy(exp); ut_assertok(ut_check_delta(start_mem)); From patchwork Thu Jun 1 16:22:54 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789247 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=HCEzD8/h; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBTJ6qC3z20QH for ; Fri, 2 Jun 2023 02:31:00 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id EA6BA865D5; Thu, 1 Jun 2023 18:25:59 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="HCEzD8/h"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id BB5FB8638A; Thu, 1 Jun 2023 18:25:21 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x136.google.com (mail-il1-x136.google.com [IPv6:2607:f8b0:4864:20::136]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 3736C8639F for ; Thu, 1 Jun 2023 18:25:13 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x136.google.com with SMTP id e9e14a558f8ab-33c1e7743b7so4034895ab.1 for ; Thu, 01 Jun 2023 09:25:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636693; x=1688228693; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=LZQWEH4oeFy0Wj1LyiYXahbjWg/CYnqisUmQJ4kBrXs=; b=HCEzD8/hx9G362L8TEM1Jwv8E3ucwre8pDOge4XPJbWnm6x96ms+I7r78qrSvz3wvu xlP3BSgLSdw/mqL4iTLAqi1jIzXNBhUj2HhfL6YZONaKGCIw/0MBpnuQD6e0KrCARC85 rq08z4DZbbVMOFpP3II277wYHzEcTKwo14VA8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636693; x=1688228693; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=LZQWEH4oeFy0Wj1LyiYXahbjWg/CYnqisUmQJ4kBrXs=; b=aQ2W8c+Kzqw3Dtxi2i1vzziFa6XqOh9aFosscE53hW94ElHrJEvBCvNY3IzXkzP/Jq ghYzMDCkqHk7nwDBASqstcNVeuKfTQqUNjxcj5d6T+pwiS/lWQCjvTlZhIgE6Vwb5J+Y nfHi89mTPpuzJx9EPS0+HEML18P1jKmLTGszCJAjC7KU9nuPMYMwJpRBWLOQg+aFJHZu vbfTDC6+tfb1eCP/wQ/+kfiVmSRs5X23f0Dg0s6o9hrRaG6kUkrVAwub8OYZZvzTnaOU MMyjRsyMdc0CmNeDPFqMfE4j4xJlTTWKIRTX/cWlm76bF686bgXEn14IbEWxXATggLQU nz7A== X-Gm-Message-State: AC+VfDwCAfkaIXxmTnmJlmzUjextHe4UsNCGrY4QnYp0r9K0rpWDTKrs sDO5nKV4JzDjEW3ixEuerd3JDHQjgScxo+ISXs8= X-Google-Smtp-Source: ACHHUZ424ARF0GyDGrPjvEiszfNagc1CMD1ZDDYzLHAhimN5pTVo3+0RaZ+8vp843gZzC1CHHaC8LQ== X-Received: by 2002:a05:6e02:5cf:b0:33b:b6b9:a79d with SMTP id l15-20020a056e0205cf00b0033bb6b9a79dmr5566392ils.31.1685636693001; Thu, 01 Jun 2023 09:24:53 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:52 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 30/40] expo: Move menu-item selection into a function Date: Thu, 1 Jun 2023 10:22:54 -0600 Message-ID: <20230601162404.220488-29-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean The current implementation supports a 'pointer' object which points to the currently highlighted menu item. We want to support highlighting the label of the menu item instead, e.g. with inverse video. In this case we will need to 'unhighlight' the old item and highlight the new one. As a first step, move the pointer logic into a function. This fixes a bug where the item is hidden when it should not be. Signed-off-by: Simon Glass --- boot/scene_menu.c | 67 ++++++++++++++++++++++++++++++++++++++--------- test/boot/expo.c | 2 +- 2 files changed, 55 insertions(+), 14 deletions(-) diff --git a/boot/scene_menu.c b/boot/scene_menu.c index fa79cecdbd93..154be7f0127f 100644 --- a/boot/scene_menu.c +++ b/boot/scene_menu.c @@ -33,6 +33,51 @@ void scene_menu_destroy(struct scene_obj_menu *menu) scene_menuitem_destroy(item); } +static struct scene_menitem *scene_menuitem_find(struct scene_obj_menu *menu, + int id) +{ + struct scene_menitem *item; + + list_for_each_entry(item, &menu->item_head, sibling) { + if (item->id == id) + return item; + } + + return NULL; +} + +/** + * update_pointers() - Update the pointer object and handle highlights + * + * @menu: Menu to update + * @id: ID of menu item to select/deselect + * @point: true if @id is being selected, false if it is being deselected + */ +static int update_pointers(struct scene_obj_menu *menu, uint id, bool point) +{ + struct scene *scn = menu->obj.scene; + const struct scene_menitem *item; + int ret; + + item = scene_menuitem_find(menu, id); + if (!item) + return log_msg_ret("itm", -ENOENT); + + /* adjust the pointer object to point to the selected item */ + if (menu->pointer_id && item && point) { + struct scene_obj *label; + + label = scene_obj_find(scn, item->label_id, SCENEOBJT_NONE); + + ret = scene_obj_set_pos(scn, menu->pointer_id, + menu->obj.dim.x + 200, label->dim.y); + if (ret < 0) + return log_msg_ret("ptr", ret); + } + + return 0; +} + /** * menu_point_to_item() - Point to a particular menu item * @@ -40,7 +85,10 @@ void scene_menu_destroy(struct scene_obj_menu *menu) */ static void menu_point_to_item(struct scene_obj_menu *menu, uint item_id) { + if (menu->cur_item_id) + update_pointers(menu, menu->cur_item_id, false); menu->cur_item_id = item_id; + update_pointers(menu, item_id, true); } static int scene_bbox_union(struct scene *scn, uint id, @@ -125,6 +173,7 @@ int scene_menu_calc_dims(struct scene_obj_menu *menu) int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu) { struct scene_menitem *item; + uint sel_id; int y, cur_y; int ret; @@ -147,7 +196,7 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu) * small. This can be updated once text measuring is supported in * vidconsole */ - cur_y = -1; + sel_id = menu->cur_item_id; list_for_each_entry(item, &menu->item_head, sibling) { int height; @@ -160,8 +209,8 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu) y += height; /* select an item if not done already */ - if (!menu->cur_item_id) - menu_point_to_item(menu, item->id); + if (!sel_id) + sel_id = item->id; /* * Put the label on the left, then leave a space for the @@ -207,16 +256,8 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu) y += height; } - if (menu->pointer_id && cur_y != -1) { - /* - * put the pointer to the right of and level with the item it - * points to - */ - ret = scene_obj_set_pos(scn, menu->pointer_id, - menu->obj.dim.x + 200, cur_y); - if (ret < 0) - return log_msg_ret("ptr", ret); - } + if (sel_id) + menu_point_to_item(menu, sel_id); return 0; } diff --git a/test/boot/expo.c b/test/boot/expo.c index c0ef03b59112..453316ece7c3 100644 --- a/test/boot/expo.c +++ b/test/boot/expo.c @@ -378,7 +378,7 @@ static int expo_object_menu(struct unit_test_state *uts) ut_asserteq(-4, prev1->obj.dim.x); ut_asserteq(menu->obj.dim.y + 32, prev1->obj.dim.y); - ut_asserteq(false, prev1->obj.flags & SCENEOF_HIDE); + ut_asserteq(true, prev1->obj.flags & SCENEOF_HIDE); expo_destroy(exp); From patchwork Thu Jun 1 16:22:55 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789255 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=X9J8Uxyo; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBVK222vz20QH for ; Fri, 2 Jun 2023 02:31:53 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id BF7C286357; Thu, 1 Jun 2023 18:26:16 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="X9J8Uxyo"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id F21668639C; Thu, 1 Jun 2023 18:25:24 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x130.google.com (mail-il1-x130.google.com [IPv6:2607:f8b0:4864:20::130]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 6BABF863A0 for ; Thu, 1 Jun 2023 18:25:13 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x130.google.com with SMTP id e9e14a558f8ab-33b0bfb76cfso3343425ab.2 for ; Thu, 01 Jun 2023 09:25:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636694; x=1688228694; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=GD/61aOvWne3wf3E8MI3nraEHMi3Tu0QjxC/95iI29g=; b=X9J8Uxyoj0jVejIRiEfrD8vm+h0gF3Qs4zVZDprXdhM0bDB8WfJgyVwUyNFzLrhXam w1XcbZMNdCvDMR1W2g5MxKQEF2W2UYguKDU0nzmo4o3jYFTMKIn/RbB2+zTqfIhm08OP M6VV0YIzehkfWdpHK0/PqVA5ZchXfOU8aYbLk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636694; x=1688228694; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=GD/61aOvWne3wf3E8MI3nraEHMi3Tu0QjxC/95iI29g=; b=CAi7B+5TOsgsIaECVK22hYMEmUi0scBdfs994YHpe5ruhvIH4xU3TrcG/mKdMZ49Yl WY4ih+phf3mPTtCRnxfgesdeJtwuBtgCTSdLRO3nCV7hBAhA0131TRmpSrnNY6wsSRWw aZPo4n3lj253lwE6ZTLu9lRzUxbhqT/7Faylxbs4b3An2vJ+VJSET1dDtdJARGO63c37 ly5QQTscYxz5o2hUwPQ/7Kcp62TaLt9GDn2rOO11afJRPRB4K5vaXFX828aSIAYwnKmR qHg6yOWXSnKT+GuwAdCAtwW5OuwvKlDBqdJ2IbvsDz+qBn3fPt891mtbH2ymuNpUbgY6 lSTw== X-Gm-Message-State: AC+VfDwb7qmucjyiXGTtv27GwssIf3/4SlR5LZ8AZIhER2NrxJ63tbY0 JVk+deH8F2K4mIPBlTrojCV2iVGzY9wDysY6ykg= X-Google-Smtp-Source: ACHHUZ6NjoenjJFtMaqmS65jRCnkF/d7LjLBAWzwoeeh2B44LmmKkcHXpP+AYhRRtU2IVSJkj/gLMQ== X-Received: by 2002:a92:c952:0:b0:33d:20ba:795f with SMTP id i18-20020a92c952000000b0033d20ba795fmr1260996ilq.32.1685636693906; Thu, 01 Jun 2023 09:24:53 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:53 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 31/40] expo: Support drawing of popup menus Date: Thu, 1 Jun 2023 10:22:55 -0600 Message-ID: <20230601162404.220488-30-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean At present only a single menu is supported. All items are shown and a pointer object points to the current item. Add support for multiple menus, one of which is highlighted, indicated by the highlight_id property in the scene. The highlighted menu item has a SCENEOF_POINT flag, indicating that it is currently pointed to. The popup menu is normally closed, in which case it shows only the current menu item. When it is opened, it shows all items, allowing the user to select one. Rather than requiring the menu item to have a description, require it to have a label. Use the label (only) for the popup menu. With this, most of the drawing and layout logic is complete. Signed-off-by: Simon Glass --- boot/scene_menu.c | 58 ++++++++++++++++++++++++++++++----------------- include/expo.h | 9 ++++++++ 2 files changed, 46 insertions(+), 21 deletions(-) diff --git a/boot/scene_menu.c b/boot/scene_menu.c index 154be7f0127f..f2832b4ddfd7 100644 --- a/boot/scene_menu.c +++ b/boot/scene_menu.c @@ -56,6 +56,7 @@ static struct scene_menitem *scene_menuitem_find(struct scene_obj_menu *menu, static int update_pointers(struct scene_obj_menu *menu, uint id, bool point) { struct scene *scn = menu->obj.scene; + const bool stack = scn->expo->popup; const struct scene_menitem *item; int ret; @@ -75,6 +76,12 @@ static int update_pointers(struct scene_obj_menu *menu, uint id, bool point) return log_msg_ret("ptr", ret); } + if (stack) { + point &= scn->highlight_id == menu->obj.id; + scene_obj_flag_clrset(scn, item->label_id, SCENEOF_POINT, + point ? SCENEOF_POINT : 0); + } + return 0; } @@ -172,11 +179,15 @@ int scene_menu_calc_dims(struct scene_obj_menu *menu) int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu) { + const bool open = menu->obj.flags & SCENEOF_OPEN; + struct expo *exp = scn->expo; + const bool stack = exp->popup; struct scene_menitem *item; uint sel_id; - int y, cur_y; + int x, y; int ret; + x = menu->obj.dim.x; y = menu->obj.dim.y; if (menu->title_id) { ret = scene_obj_set_pos(scn, menu->title_id, menu->obj.dim.x, y); @@ -187,7 +198,10 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu) if (ret < 0) return log_msg_ret("hei", ret); - y += ret * 2; + if (stack) + x += 200; + else + y += ret * 2; } /* @@ -198,9 +212,10 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu) */ sel_id = menu->cur_item_id; list_for_each_entry(item, &menu->item_head, sibling) { + bool selected; int height; - ret = scene_obj_get_hw(scn, item->desc_id, NULL); + ret = scene_obj_get_hw(scn, item->label_id, NULL); if (ret < 0) return log_msg_ret("get", ret); height = ret; @@ -212,29 +227,29 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu) if (!sel_id) sel_id = item->id; + selected = sel_id == item->id; + /* * Put the label on the left, then leave a space for the * pointer, then the key and the description */ - if (item->label_id) { - ret = scene_obj_set_pos(scn, item->label_id, menu->obj.dim.x, - y); - if (ret < 0) - return log_msg_ret("nam", ret); - } - - ret = scene_obj_set_pos(scn, item->key_id, menu->obj.dim.x + 230, - y); + ret = scene_obj_set_pos(scn, item->label_id, x, y); if (ret < 0) - return log_msg_ret("key", ret); + return log_msg_ret("nam", ret); + scene_obj_set_hide(scn, item->label_id, + stack && !open && !selected); - ret = scene_obj_set_pos(scn, item->desc_id, menu->obj.dim.x + 280, - y); - if (ret < 0) - return log_msg_ret("des", ret); + if (item->key_id) { + ret = scene_obj_set_pos(scn, item->key_id, x + 230, y); + if (ret < 0) + return log_msg_ret("key", ret); + } - if (menu->cur_item_id == item->id) - cur_y = y; + if (item->desc_id) { + ret = scene_obj_set_pos(scn, item->desc_id, x + 280, y); + if (ret < 0) + return log_msg_ret("des", ret); + } if (item->preview_id) { bool hide; @@ -253,7 +268,8 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu) return log_msg_ret("hid", ret); } - y += height; + if (!stack || open) + y += height; } if (sel_id) @@ -380,7 +396,7 @@ int scene_menuitem(struct scene *scn, uint menu_id, const char *name, uint id, return log_msg_ret("find", -ENOENT); /* Check that the text ID is valid */ - if (!scene_obj_find(scn, desc_id, SCENEOBJT_TEXT)) + if (!scene_obj_find(scn, label_id, SCENEOBJT_TEXT)) return log_msg_ret("txt", -EINVAL); item = calloc(1, sizeof(struct scene_obj_menu)); diff --git a/include/expo.h b/include/expo.h index ea8f38913d8e..0c55d60f71a7 100644 --- a/include/expo.h +++ b/include/expo.h @@ -70,6 +70,7 @@ struct expo_theme { * @action: Action selected by user. At present only one is supported, with the * type set to EXPOACT_NONE if there is no action * @text_mode: true to use text mode for the menu (no vidconsole) + * @popup: true to use popup menus, instead of showing all items * @priv: Private data for the controller * @theme: Information about fonts styles, etc. * @scene_head: List of scenes @@ -83,6 +84,7 @@ struct expo { uint next_id; struct expo_action action; bool text_mode; + bool popup; void *priv; struct expo_theme theme; struct list_head scene_head; @@ -111,6 +113,7 @@ struct expo_string { * @name: Name of the scene (allocated) * @id: ID number of the scene * @title_id: String ID of title of the scene (allocated) + * @highlight_id: ID of highlighted object, if any * @sibling: Node to link this scene to its siblings * @obj_head: List of objects in the scene */ @@ -119,6 +122,7 @@ struct scene { char *name; uint id; uint title_id; + uint highlight_id; struct list_head sibling; struct list_head obj_head; }; @@ -157,9 +161,14 @@ struct scene_dim { * enum scene_obj_flags_t - flags for objects * * @SCENEOF_HIDE: object should be hidden + * @SCENEOF_POINT: object should be highlighted + * @SCENEOF_OPEN: object should be opened (e.g. menu is opened so that an option + * can be selected) */ enum scene_obj_flags_t { SCENEOF_HIDE = 1 << 0, + SCENEOF_POINT = 1 << 1, + SCENEOF_OPEN = 1 << 2, }; /** From patchwork Thu Jun 1 16:22:56 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789256 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=alfaJWb5; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBVY73g1z20QH for ; Fri, 2 Jun 2023 02:32:05 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 35F43865D9; Thu, 1 Jun 2023 18:26:19 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="alfaJWb5"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id F297D863A5; Thu, 1 Jun 2023 18:25:26 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-io1-xd36.google.com (mail-io1-xd36.google.com [IPv6:2607:f8b0:4864:20::d36]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 5C297863A7 for ; Thu, 1 Jun 2023 18:25:14 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd36.google.com with SMTP id ca18e2360f4ac-7747df5b674so1950639f.3 for ; Thu, 01 Jun 2023 09:25:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636694; x=1688228694; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=wDEDhkzim+UFe1OYM6/NZ5gXLeCAnS+Whr4hj2k0PH4=; b=alfaJWb5fgwaCdHpXRkTHKwnuS/84/CHl4BVj3JzJv52EI0ZnTs6g0UZSImVnMP47O NZfsexn5uttvwMrq4LdbRTk9D59G2eTN4kjOHQcRZXmcUrwxnu5zJTi7VPq77a15FbHl 55DypsbTO9R3UR/szZDxoUQe2TInbW9KKnIJ0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636694; x=1688228694; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=wDEDhkzim+UFe1OYM6/NZ5gXLeCAnS+Whr4hj2k0PH4=; b=ifj7fNSrfevHXjymlyzZgO7mFi9/zvhJGACP5GU2h5fOjc5w8+BMhM4LDo8hSjeEMH 9VlcQWtM5KaoBWfsfYlb/qsY9XbDP57QX1IpZm3Ad7ps93tVgUqfn9BxM3g3duQXtjSr /vUEItke2MKVG5M0CJVGJcJuj30YAFiC2Cu8b6wLR3Qf/881XiGmsbGMRoNFkElU8Xvv MMPeAYajNovdchZpgDBBVOhOSkRECAFGpf8tGNndKOpoXmKId6lvmcJQ+4oZ1HgOZ+0i 7Ax5VSUVfUpXmV96ki2OMAUvYM9BG4nH6kTt/9Gb9VqHtXp3kvpFYb+/Ey2uVKk6/LXn A3vg== X-Gm-Message-State: AC+VfDwWaxKhU8JIq963MgmtUDOCER5rJxs19mcpOy+NsaX92qXctFDV 9ETBBk+UVCiB5Cy3JQiPct/W8BtM6jpxCneC9No= X-Google-Smtp-Source: ACHHUZ6lFQ35wTgYsts7cAy2/jvOUySZXVxAF7Vi4ufoz6NimDgRNhROLNeNqvQU03Q0UnhsMCZUHQ== X-Received: by 2002:a92:d1c3:0:b0:332:dd0a:c6df with SMTP id u3-20020a92d1c3000000b00332dd0ac6dfmr6673538ilg.22.1685636694749; Thu, 01 Jun 2023 09:24:54 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:54 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 32/40] expo: Rename EXPOACT_POINT to EXPOACT_POINT_ITEM Date: Thu, 1 Jun 2023 10:22:56 -0600 Message-ID: <20230601162404.220488-31-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean At present we only support a single menu, so all that can be pointed to is the current menu item. Rename this action so that we can also add an action for pointing to an object. This will allow cycling through the objects in a scene. Signed-off-by: Simon Glass --- boot/scene_menu.c | 4 ++-- include/expo.h | 6 +++--- test/boot/expo.c | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/boot/scene_menu.c b/boot/scene_menu.c index f2832b4ddfd7..892099557a99 100644 --- a/boot/scene_menu.c +++ b/boot/scene_menu.c @@ -347,7 +347,7 @@ int scene_menu_send_key(struct scene *scn, struct scene_obj_menu *menu, int key, struct scene_menitem, sibling)) { item = list_entry(item->sibling.prev, struct scene_menitem, sibling); - event->type = EXPOACT_POINT; + event->type = EXPOACT_POINT_ITEM; event->select.id = item->id; log_debug("up to item %d\n", event->select.id); } @@ -356,7 +356,7 @@ int scene_menu_send_key(struct scene *scn, struct scene_obj_menu *menu, int key, if (!list_is_last(&item->sibling, &menu->item_head)) { item = list_entry(item->sibling.next, struct scene_menitem, sibling); - event->type = EXPOACT_POINT; + event->type = EXPOACT_POINT_ITEM; event->select.id = item->id; log_debug("down to item %d\n", event->select.id); } diff --git a/include/expo.h b/include/expo.h index 0c55d60f71a7..0f4388897883 100644 --- a/include/expo.h +++ b/include/expo.h @@ -16,13 +16,13 @@ struct udevice; * enum expoact_type - types of actions reported by the expo * * @EXPOACT_NONE: no action - * @EXPOACT_POINT: menu item was highlighted (@id indicates which) + * @EXPOACT_POINT_ITEM: menu item was highlighted (@id indicates which) * @EXPOACT_SELECT: menu item was selected (@id indicates which) * @EXPOACT_QUIT: request to exit the menu */ enum expoact_type { EXPOACT_NONE, - EXPOACT_POINT, + EXPOACT_POINT_ITEM, EXPOACT_SELECT, EXPOACT_QUIT, }; @@ -31,7 +31,7 @@ enum expoact_type { * struct expo_action - an action report by the expo * * @type: Action type (EXPOACT_NONE if there is no action) - * @select: Used for EXPOACT_POINT and EXPOACT_SELECT + * @select: Used for EXPOACT_POINT_ITEM and EXPOACT_SELECT * @id: ID number of the object affected. */ struct expo_action { diff --git a/test/boot/expo.c b/test/boot/expo.c index 453316ece7c3..c34eaeedd66f 100644 --- a/test/boot/expo.c +++ b/test/boot/expo.c @@ -530,7 +530,7 @@ static int expo_render_image(struct unit_test_state *uts) ut_assertok(expo_action_get(exp, &act)); - ut_asserteq(EXPOACT_POINT, act.type); + ut_asserteq(EXPOACT_POINT_ITEM, act.type); ut_asserteq(ITEM2, act.select.id); ut_assertok(expo_render(exp)); @@ -570,7 +570,7 @@ static int expo_render_image(struct unit_test_state *uts) ut_assertok(expo_action_get(exp, &act)); - ut_asserteq(EXPOACT_POINT, act.type); + ut_asserteq(EXPOACT_POINT_ITEM, act.type); ut_asserteq(ITEM1, act.select.id); ut_assertok(expo_render(exp)); From patchwork Thu Jun 1 16:22:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789249 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=DoJl9Hit; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBTq1TJ2z20QH for ; Fri, 2 Jun 2023 02:31:27 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 56CE9865D7; Thu, 1 Jun 2023 18:26:09 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="DoJl9Hit"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 6B632863BE; Thu, 1 Jun 2023 18:25:24 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x12a.google.com (mail-il1-x12a.google.com [IPv6:2607:f8b0:4864:20::12a]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id D7EAC8631B for ; Thu, 1 Jun 2023 18:25:15 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x12a.google.com with SMTP id e9e14a558f8ab-33c1e7743b7so4034975ab.1 for ; Thu, 01 Jun 2023 09:25:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636695; x=1688228695; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=zUr7aZaJVDZ8u7XLZs8MSWdcs0CudfXzZTZyncC+xlE=; b=DoJl9Hit+DuHXinfeUfq5eNCAUXHX/V7Z63P8nyceQgi+rc96o4SfbG0EipOhNsawt aocoxvvfjyvHYy9ol1ksgRvi5v4fsxL/05r/1h8fro024ClgWulWktgxq6195GLhhVqs vMw7e9Zc3Wp6S5tEGJaENC0nn8i43ZEnNQms4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636695; x=1688228695; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=zUr7aZaJVDZ8u7XLZs8MSWdcs0CudfXzZTZyncC+xlE=; b=IS++91eN+Md/nY6X45oPi7rWclqctZTDWVPvfGJrEnKJQUgFR7CmvNhamX6qk5+HUn EYYUSdkSghlIKefPotupuItfSiL7PaFjAOjnuLniBxLoEqH3oA5/IqkjLDitIuy+Fbsb QfhatMgBsIELvQnin6c31hP7RZ4qvu90I+b96gg+f71UYxXH43OVWZNpM/WA/KwhSn9Q yrMVyIna6MBKMl0+IwL1Di+bB6y9CSUsodvmZluq/jwkM7R5R+5tP4ewRoPtZptmzJvH GBUv2v+Ql+YQIVcp9WciOuQbxwE2mrTwnAEa49zDL6tg22z68S3XhQ741unogBwUeqKd wFWw== X-Gm-Message-State: AC+VfDwOhCqkMub2uxOg85As9Vq64+KCBXel3naRjVd3cTV+VYzUC/NE eBXUVb8fAE/MFsZ5XdJyD4bCSEqlkeDBSnezTOk= X-Google-Smtp-Source: ACHHUZ50N8kqSl3XXzKbK2LXDSzzz1M/L2Mo0GLnqp3z6WDS6z80QfnvH5Bt3TNN2164hvQt0d4v3Q== X-Received: by 2002:a92:da0b:0:b0:33c:5182:6cf1 with SMTP id z11-20020a92da0b000000b0033c51826cf1mr4729425ilm.27.1685636695520; Thu, 01 Jun 2023 09:24:55 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:55 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 33/40] expo: Draw popup menus in both opened and closed states Date: Thu, 1 Jun 2023 10:22:57 -0600 Message-ID: <20230601162404.220488-32-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean When a popup menu is closed it shows only the selected item. When it is open it shows a background and all items, with a highlight that can be moved between the items. Add the drawing logic for this. Signed-off-by: Simon Glass --- boot/scene.c | 66 +++++++++++++++++++++++++++++++++++++++++-- boot/scene_internal.h | 7 +++++ boot/scene_menu.c | 29 +++++++++++++++++++ include/expo.h | 30 ++++++++++++++++++++ 4 files changed, 130 insertions(+), 2 deletions(-) diff --git a/boot/scene.c b/boot/scene.c index 4dbe12a2b740..fb199ef29538 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -345,14 +345,44 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode) } if (ret && ret != -ENOSYS) return log_msg_ret("font", ret); - vidconsole_set_cursor_pos(cons, x, y); str = expo_get_str(exp, txt->str_id); - if (str) + if (str) { + struct video_priv *vid_priv; + struct vidconsole_colour old; + enum colour_idx fore, back; + + if (CONFIG_IS_ENABLED(SYS_WHITE_ON_BLACK)) { + fore = VID_BLACK; + back = VID_WHITE; + } else { + fore = VID_LIGHT_GRAY; + back = VID_BLACK; + } + + vid_priv = dev_get_uclass_priv(dev); + if (obj->flags & SCENEOF_POINT) { + vidconsole_push_colour(cons, fore, back, &old); + video_fill_part(dev, x, y, + x + obj->dim.w, y + obj->dim.h, + vid_priv->colour_bg); + } + vidconsole_set_cursor_pos(cons, x, y); vidconsole_put_string(cons, str); + if (obj->flags & SCENEOF_POINT) + vidconsole_pop_colour(cons, &old); + } break; } case SCENEOBJT_MENU: { struct scene_obj_menu *menu = (struct scene_obj_menu *)obj; + + if (exp->popup && (obj->flags & SCENEOF_OPEN)) { + if (!cons) + return -ENOTSUPP; + + /* draw a background behind the menu items */ + scene_menu_render(menu); + } /* * With a vidconsole, the text and item pointer are rendered as * normal objects so we don't need to do anything here. The menu @@ -494,3 +524,35 @@ int scene_apply_theme(struct scene *scn, struct expo_theme *theme) return 0; } + +void scene_set_highlight_id(struct scene *scn, uint id) +{ + scn->highlight_id = id; +} + +void scene_highlight_first(struct scene *scn) +{ + struct scene_obj *obj; + + list_for_each_entry(obj, &scn->obj_head, sibling) { + switch (obj->type) { + case SCENEOBJT_MENU: + scene_set_highlight_id(scn, obj->id); + return; + default: + break; + } + } +} + +int scene_set_open(struct scene *scn, uint id, bool open) +{ + int ret; + + ret = scene_obj_flag_clrset(scn, id, SCENEOF_OPEN, + open ? SCENEOF_OPEN : 0); + if (ret) + return log_msg_ret("flg", ret); + + return 0; +} diff --git a/boot/scene_internal.h b/boot/scene_internal.h index 3387a90761ab..2544c961dab4 100644 --- a/boot/scene_internal.h +++ b/boot/scene_internal.h @@ -153,6 +153,13 @@ int scene_render(struct scene *scn); */ int scene_send_key(struct scene *scn, int key, struct expo_action *event); +/** + * scene_menu_render() - Render the background behind a menu + * + * @menu: Menu to render + */ +void scene_menu_render(struct scene_obj_menu *menu); + /** * scene_menu_calc_dims() - Calculate the dimensions of a menu * diff --git a/boot/scene_menu.c b/boot/scene_menu.c index 892099557a99..20ded91fb3d6 100644 --- a/boot/scene_menu.c +++ b/boot/scene_menu.c @@ -515,3 +515,32 @@ int scene_menu_display(struct scene_obj_menu *menu) return -ENOTSUPP; } + +void scene_menu_render(struct scene_obj_menu *menu) +{ + struct expo *exp = menu->obj.scene->expo; + const struct expo_theme *theme = &exp->theme; + struct vidconsole_bbox bbox, label_bbox; + struct udevice *dev = exp->display; + struct video_priv *vid_priv; + struct udevice *cons = exp->cons; + struct vidconsole_colour old; + enum colour_idx fore, back; + + if (CONFIG_IS_ENABLED(SYS_WHITE_ON_BLACK)) { + fore = VID_BLACK; + back = VID_WHITE; + } else { + fore = VID_LIGHT_GRAY; + back = VID_BLACK; + } + + scene_menu_calc_bbox(menu, &bbox, &label_bbox); + vidconsole_push_colour(cons, fore, back, &old); + vid_priv = dev_get_uclass_priv(dev); + video_fill_part(dev, label_bbox.x0 - theme->menu_inset, + label_bbox.y0 - theme->menu_inset, + label_bbox.x1, label_bbox.y1 + theme->menu_inset, + vid_priv->colour_fg); + vidconsole_pop_colour(cons, &old); +} diff --git a/include/expo.h b/include/expo.h index 0f4388897883..0699cdb4c19c 100644 --- a/include/expo.h +++ b/include/expo.h @@ -412,6 +412,36 @@ int scene_new(struct expo *exp, const char *name, uint id, struct scene **scnp); */ struct scene *expo_lookup_scene_id(struct expo *exp, uint scene_id); +/** + * scene_highlight_first() - Highlight the first item in a scene + * + * This highlights the first item, so that the user can see that it is pointed + * to + * + * @scn: Scene to update + */ +void scene_highlight_first(struct scene *scn); + +/** + * scene_set_highlight_id() - Set the object which is highlighted + * + * Sets a new object to highlight in the scene + * + * @scn: Scene to update + * @id: ID of object to highlight + */ +void scene_set_highlight_id(struct scene *scn, uint id); + +/** + * scene_set_open() - Set whether an item is open or not + * + * @scn: Scene to update + * @id: ID of object to update + * @open: true to open the object, false to close it + * Returns: 0 if OK, -ENOENT if @id is invalid + */ +int scene_set_open(struct scene *scn, uint id, bool open); + /** * scene_title_set() - set the scene title * From patchwork Thu Jun 1 16:22:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789252 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=Vzn8Bx9b; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBV4497dz20QH for ; Fri, 2 Jun 2023 02:31:40 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id E925D865DF; Thu, 1 Jun 2023 18:26:13 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="Vzn8Bx9b"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id A873B8631B; Thu, 1 Jun 2023 18:25:24 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x132.google.com (mail-il1-x132.google.com [IPv6:2607:f8b0:4864:20::132]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 680AB8638C for ; Thu, 1 Jun 2023 18:25:16 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x132.google.com with SMTP id e9e14a558f8ab-33bdab7b4caso3595455ab.3 for ; Thu, 01 Jun 2023 09:25:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636696; x=1688228696; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=iZSmc7CwK/GjANpuPpzhxVaHpT2pm4WuXZD/vB56DBQ=; b=Vzn8Bx9bZ4ORAot8/3LgXZHJn9EUZxu4QfwX0V+H+NLUylPmzni12MLSml8yl19FH8 nn0skPPqb97ENy7hFMBfftG7KZMVt+owGW3I9FfdBIiYiIVtYUnHxxpabf1H/PeRofkt LoYYnrluSz7EKS+aJVglu41Qferlwb32H/288= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636696; x=1688228696; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=iZSmc7CwK/GjANpuPpzhxVaHpT2pm4WuXZD/vB56DBQ=; b=fPsJNUsdkZ2rzOozZtPKlcgzPVlGv1pkc0zHUmkwCn/8YX6H1H/nfC2nuoDt9GLzXH oGZcw1LfPJJzAMOcPoSstBH/4fzZPdN56rI6aAfohYW0oMuz7Gsw2tx1AHH9MHxXNdro ap23xRWDxrmO+dvTmUvtN/QUgXR0T2z4UKPfMhVUdjeAJA28e75WTVkfC0Yxc8Awa0Wi 1NcRQhccrPv5+IaLbRMr1aHMH7fFQ3sFjy1EmcfMo13UWUpKipXXSIsmXfgLMZhG8oZu FFzFzUs/O0DJYGFYc9Ae6CP55K9MScOfUFcWaCZ25AvSis4N7qZKpRolZ6FOZ5uw5P61 E7yA== X-Gm-Message-State: AC+VfDz1rJUcmDba2vF7jtavTPg5HJqyDP4lSZ7NaKaptEUxFxnH1UJo cxkjUmSkg8DcZTE91asRrVSR3psu1Re7OnLs8Qg= X-Google-Smtp-Source: ACHHUZ6S08/mWQaJMezQDn0PdzAMBiQbfJebMV3AskOc6jNXSFJStzEZpkoywBUt61ePBg/keN2hjQ== X-Received: by 2002:a92:d352:0:b0:329:5a6e:3a18 with SMTP id a18-20020a92d352000000b003295a6e3a18mr4777301ilh.4.1685636696298; Thu, 01 Jun 2023 09:24:56 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:56 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 34/40] expo: Draw the current opened menu on top Date: Thu, 1 Jun 2023 10:22:58 -0600 Message-ID: <20230601162404.220488-33-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean When a menu is opened, it must be displayed over all other objects in the scene, so that all its items are visible. Handle this by drawing the menu object a second time, after all other objects have been drawn. Draw all of the objects which are dependent on the menu object. Signed-off-by: Simon Glass --- boot/expo.c | 12 ++++++++++++ boot/scene.c | 31 +++++++++++++++++++++++++++++++ boot/scene_internal.h | 20 ++++++++++++++++++++ boot/scene_menu.c | 17 +++++++++++++++++ 4 files changed, 80 insertions(+) diff --git a/boot/expo.c b/boot/expo.c index d5e935966bfd..e99555163ca4 100644 --- a/boot/expo.c +++ b/boot/expo.c @@ -172,6 +172,18 @@ int expo_set_scene_id(struct expo *exp, uint scene_id) return 0; } +int expo_first_scene_id(struct expo *exp) +{ + struct scene *scn; + + if (list_empty(&exp->scene_head)) + return -ENOENT; + + scn = list_first_entry(&exp->scene_head, struct scene, sibling); + + return scn->id; +} + int expo_render(struct expo *exp) { struct udevice *dev = exp->display; diff --git a/boot/scene.c b/boot/scene.c index fb199ef29538..bc213bc08b87 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -421,6 +421,30 @@ int scene_arrange(struct scene *scn) return 0; } +int scene_render_deps(struct scene *scn, uint id) +{ + struct scene_obj *obj; + int ret; + + if (!id) + return 0; + obj = scene_obj_find(scn, id, SCENEOBJT_NONE); + if (!obj) + return log_msg_ret("obj", -ENOENT); + + if (!(obj->flags & SCENEOF_HIDE)) { + ret = scene_obj_render(obj, false); + if (ret && ret != -ENOTSUPP) + return log_msg_ret("ren", ret); + + if (obj->type == SCENEOBJT_MENU) + scene_menu_render_deps(scn, + (struct scene_obj_menu *)obj); + } + + return 0; +} + int scene_render(struct scene *scn) { struct expo *exp = scn->expo; @@ -435,6 +459,13 @@ int scene_render(struct scene *scn) } } + /* render any highlighted object on top of the others */ + if (scn->highlight_id && !exp->text_mode) { + ret = scene_render_deps(scn, scn->highlight_id); + if (ret && ret != -ENOTSUPP) + return log_msg_ret("dep", ret); + } + return 0; } diff --git a/boot/scene_internal.h b/boot/scene_internal.h index 2544c961dab4..dc98ecd02146 100644 --- a/boot/scene_internal.h +++ b/boot/scene_internal.h @@ -160,6 +160,26 @@ int scene_send_key(struct scene *scn, int key, struct expo_action *event); */ void scene_menu_render(struct scene_obj_menu *menu); +/** + * scene_render_deps() - Render an object and its dependencies + * + * @scn: Scene to render + * @id: Object ID to render (or 0 for none) + * Returns: 0 if OK, -ve on error + */ +int scene_render_deps(struct scene *scn, uint id); + +/** + * scene_menu_render_deps() - Render a menu and its dependencies + * + * Renders the menu and all of its attached objects + * + * @scn: Scene to render + * @menu: Menu render + * Returns: 0 if OK, -ve on error + */ +int scene_menu_render_deps(struct scene *scn, struct scene_obj_menu *menu); + /** * scene_menu_calc_dims() - Calculate the dimensions of a menu * diff --git a/boot/scene_menu.c b/boot/scene_menu.c index 20ded91fb3d6..6aab27611d71 100644 --- a/boot/scene_menu.c +++ b/boot/scene_menu.c @@ -544,3 +544,20 @@ void scene_menu_render(struct scene_obj_menu *menu) vid_priv->colour_fg); vidconsole_pop_colour(cons, &old); } + +int scene_menu_render_deps(struct scene *scn, struct scene_obj_menu *menu) +{ + struct scene_menitem *item; + + scene_render_deps(scn, menu->title_id); + scene_render_deps(scn, menu->cur_item_id); + scene_render_deps(scn, menu->pointer_id); + + list_for_each_entry(item, &menu->item_head, sibling) { + scene_render_deps(scn, item->key_id); + scene_render_deps(scn, item->label_id); + scene_render_deps(scn, item->desc_id); + } + + return 0; +} From patchwork Thu Jun 1 16:22:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789258 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=PgKhX6s7; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBVq1k9Cz20QH for ; Fri, 2 Jun 2023 02:32:19 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 880D1865E6; Thu, 1 Jun 2023 18:26:23 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="PgKhX6s7"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 0BA1E863B8; Thu, 1 Jun 2023 18:25:31 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x133.google.com (mail-il1-x133.google.com [IPv6:2607:f8b0:4864:20::133]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 505AB86358 for ; Thu, 1 Jun 2023 18:25:19 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x133.google.com with SMTP id e9e14a558f8ab-33bdab7b4caso3595605ab.3 for ; Thu, 01 Jun 2023 09:25:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636697; x=1688228697; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=tGD6MzhqSmyCNDC1Zlb54nxtR6BHRDCBpAHvEnpKuHQ=; b=PgKhX6s7z+YlIPeOTUzlebrraupNE6MbXz+CnQaiYAwn3EcZ6I54FOlz+NCGd5EfRx mjrQTMMRIi7vOpPSWzbR5uv2M+5Ek/3IXuU+8inJliPNEZxpFe5VwHEN1hZQW7IRsEgx fZRHT477jfBtrH+6OloexVWyB7Ykr9J7NEJ20= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636697; x=1688228697; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=tGD6MzhqSmyCNDC1Zlb54nxtR6BHRDCBpAHvEnpKuHQ=; b=IPkvaCu+5trODlaSQKTIeZxv1NXV39ExIKdCp0VGwBZ8fnDAKyK2S7ttQp+Jxzn1mf 9iERYXB9X1Vpy1+k8h7/DqHbwSQNSNG1N7eMduTADaLWauIFzA5x1rtjz9gQxZCfdtMY YlhzOE8qAyEvm2Wt0hQY2gqW3rzvEJPMGDhC5/jnYpHlkip6VYxQa5ptNpFTI1KzdSoS GoIjGiBVOU9RUKHU8zWHmIPbhMB+hIm+B8PY9XyNCrW4NPP/yHrvA7QLiP/09U/dv/uI HkaSdtC8yOT++vGDIWvY3RQBdLv4PUQVbYMQU+0riBRoj5AkyOZn7pG7C/qVkztqwURU yqHA== X-Gm-Message-State: AC+VfDx93eNh/615HyuEpQrb6202Ti99OK7zUl51JGBneEo1UhF46b7h t7Ov+vLctb0nEYIxk6kBL5edqqyXz02twxA7hIs= X-Google-Smtp-Source: ACHHUZ7LFDn7skoBXl7E7qIRPB7+pOSakzNOyA2vv7+djdCwcR7d8OMTmh1SR1vCkSyhs5GVK1wObA== X-Received: by 2002:a92:c644:0:b0:32c:bd05:9b2f with SMTP id 4-20020a92c644000000b0032cbd059b2fmr368000ill.27.1685636697171; Thu, 01 Jun 2023 09:24:57 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:56 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 35/40] expo: Implement the keypress logic for popup menus Date: Thu, 1 Jun 2023 10:22:59 -0600 Message-ID: <20230601162404.220488-34-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean In 'popup' mode, the expo allows moving around the objects in a scene. When 'enter' is pressed on a menu, it opens and the user can move around the items in the menu. Implement this using keypress handles and actions. Signed-off-by: Simon Glass --- boot/scene.c | 80 ++++++++++++++++++++++++++++++++++++++++++++ boot/scene_menu.c | 10 ++++-- doc/develop/expo.rst | 3 +- include/expo.h | 7 ++++ 4 files changed, 96 insertions(+), 4 deletions(-) diff --git a/boot/scene.c b/boot/scene.c index bc213bc08b87..ea94b90584ee 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -469,11 +470,90 @@ int scene_render(struct scene *scn) return 0; } +/** + * send_key_obj() - Handle a keypress for moving between objects + * + * @scn: Scene to receive the key + * @key: Key to send (KEYCODE_UP) + * @event: Returns resulting event from this keypress + * Returns: 0 if OK, -ve on error + */ +static void send_key_obj(struct scene *scn, struct scene_obj *obj, int key, + struct expo_action *event) +{ + switch (key) { + case BKEY_UP: + while (obj != list_first_entry(&scn->obj_head, struct scene_obj, + sibling)) { + obj = list_entry(obj->sibling.prev, + struct scene_obj, sibling); + if (obj->type == SCENEOBJT_MENU) { + event->type = EXPOACT_POINT_OBJ; + event->select.id = obj->id; + log_debug("up to obj %d\n", event->select.id); + break; + } + } + break; + case BKEY_DOWN: + while (!list_is_last(&obj->sibling, &scn->obj_head)) { + obj = list_entry(obj->sibling.next, struct scene_obj, + sibling); + if (obj->type == SCENEOBJT_MENU) { + event->type = EXPOACT_POINT_OBJ; + event->select.id = obj->id; + log_debug("down to obj %d\n", event->select.id); + break; + } + } + break; + case BKEY_SELECT: + if (obj->type == SCENEOBJT_MENU) { + event->type = EXPOACT_OPEN; + event->select.id = obj->id; + log_debug("open obj %d\n", event->select.id); + } + break; + case BKEY_QUIT: + event->type = EXPOACT_QUIT; + log_debug("obj quit\n"); + break; + } +} + int scene_send_key(struct scene *scn, int key, struct expo_action *event) { + struct scene_obj_menu *menu; struct scene_obj *obj; int ret; + event->type = EXPOACT_NONE; + + /* + * In 'popup' mode, arrow keys move betwen objects, unless a menu is + * opened + */ + if (scn->expo->popup) { + obj = NULL; + if (scn->highlight_id) { + obj = scene_obj_find(scn, scn->highlight_id, + SCENEOBJT_NONE); + } + if (!obj) + return 0; + + if (!(obj->flags & SCENEOF_OPEN)) { + send_key_obj(scn, obj, key, event); + return 0; + } + + menu = (struct scene_obj_menu *)obj, + ret = scene_menu_send_key(scn, menu, key, event); + if (ret) + return log_msg_ret("key", ret); + return 0; + } + list_for_each_entry(obj, &scn->obj_head, sibling) { if (obj->type == SCENEOBJT_MENU) { struct scene_obj_menu *menu; diff --git a/boot/scene_menu.c b/boot/scene_menu.c index 6aab27611d71..dfe5692d6ce7 100644 --- a/boot/scene_menu.c +++ b/boot/scene_menu.c @@ -323,6 +323,7 @@ static struct scene_menitem *scene_menu_find_key(struct scene *scn, int scene_menu_send_key(struct scene *scn, struct scene_obj_menu *menu, int key, struct expo_action *event) { + const bool open = menu->obj.flags & SCENEOF_OPEN; struct scene_menitem *item, *cur, *key_item; cur = NULL; @@ -367,8 +368,13 @@ int scene_menu_send_key(struct scene *scn, struct scene_obj_menu *menu, int key, log_debug("select item %d\n", event->select.id); break; case BKEY_QUIT: - event->type = EXPOACT_QUIT; - log_debug("quit\n"); + if (scn->expo->popup && open) { + event->type = EXPOACT_CLOSE; + event->select.id = menu->obj.id; + } else { + event->type = EXPOACT_QUIT; + log_debug("menu quit\n"); + } break; case '0'...'9': key_item = scene_menu_find_key(scn, menu, key); diff --git a/doc/develop/expo.rst b/doc/develop/expo.rst index 2f4882899b6d..80e435c5e65e 100644 --- a/doc/develop/expo.rst +++ b/doc/develop/expo.rst @@ -178,8 +178,7 @@ Some ideas for future work: - Image formats other than BMP - Use of ANSI sequences to control a serial terminal - Colour selection -- Better support for handling lots of settings, e.g. with multiple menus and - radio/option widgets +- Better support for handling lots of settings, e.g. with radio/option widgets - Mouse support - Integrate Nuklear, NxWidgets or some other library for a richer UI - Optimise rendering by only updating the display with changes since last render diff --git a/include/expo.h b/include/expo.h index 0699cdb4c19c..f7febe1c9ae7 100644 --- a/include/expo.h +++ b/include/expo.h @@ -16,14 +16,21 @@ struct udevice; * enum expoact_type - types of actions reported by the expo * * @EXPOACT_NONE: no action + * @EXPOACT_POINT_OBJ: object was highlighted (@id indicates which) * @EXPOACT_POINT_ITEM: menu item was highlighted (@id indicates which) * @EXPOACT_SELECT: menu item was selected (@id indicates which) + * @EXPOACT_OPEN: menu was opened, so an item can be selected (@id indicates + * which menu object) + * @EXPOACT_CLOSE: menu was closed (@id indicates which menu object) * @EXPOACT_QUIT: request to exit the menu */ enum expoact_type { EXPOACT_NONE, + EXPOACT_POINT_OBJ, EXPOACT_POINT_ITEM, EXPOACT_SELECT, + EXPOACT_OPEN, + EXPOACT_CLOSE, EXPOACT_QUIT, }; From patchwork Thu Jun 1 16:23:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789261 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=AlLwwh/d; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBW44RBrz20QH for ; Fri, 2 Jun 2023 02:32:32 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 16C26865F4; Thu, 1 Jun 2023 18:26:28 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="AlLwwh/d"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 68F09863A5; Thu, 1 Jun 2023 18:25:30 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x132.google.com (mail-il1-x132.google.com [IPv6:2607:f8b0:4864:20::132]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id E9E0B863B8 for ; Thu, 1 Jun 2023 18:25:25 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x132.google.com with SMTP id e9e14a558f8ab-33b3f2f7989so3489175ab.0 for ; Thu, 01 Jun 2023 09:25:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636698; x=1688228698; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=vfNzoxBLAO9R21kc4Sg0/fn1H5MqRFCw30Ikmz/eOVc=; b=AlLwwh/dw/r/XJzR+bn+oQKvwZY1s3J9Ywt7IdMPS/vaX6RuppfMPwutXoVxxcbxHy Gf8deieaNBJT3V04niHaEq0DpDLQlTzd60pEi9d/lS4hjam3uZVUPXKUbTObgNycwwQ5 HTYQNRKQbRCCLKlLFYOBpSjRqbn0uM8pbZ9yY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636698; x=1688228698; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=vfNzoxBLAO9R21kc4Sg0/fn1H5MqRFCw30Ikmz/eOVc=; b=Sg0/DiazcCW3pLdzdA98FBRvaUSuo/pwtkFbm1Hi6YJeIaJNDTaS1OPL4SiNjssldN hMqI7sc19R/4EWGCaz5HozLiTM9aSQLa0IBxF92CyEt26zmhUx759gBsGFIefSVs9NjA n+WXuRD9cgasVEdbhvnzESD6V/nAZyx2bX8q/kruhzDay7UExCyalP9e398lgk+wP9e1 JU+NzMYhCGJwW89HwE78kg0Hm3bkF06NJWsRJG6la+VpMpd9n33aUn+NcBq83kObhCJ1 UjUcBLrplqmam+lzdXUMH2hJ3aVSj5U/mJIE+NIxLpwNzuQnm4Y1PspexFBcwjL/GsPW 4qiA== X-Gm-Message-State: AC+VfDyTVtFdv8ID5fgySTTKh+EvflDJf9dUt/HuQEia/pso5WiPEptT ksJ4xOqip2/ulfeEk7H5WDwXpA5XACe1BZO0/qw= X-Google-Smtp-Source: ACHHUZ5g4jKX1Y0ZYNLjm0eVr6dwgWAgJtHQSSBMggMwrGZQ0nznIvTVVCCR4lbyqRYxhaJc3Eg0UQ== X-Received: by 2002:a92:c990:0:b0:325:b96e:6701 with SMTP id y16-20020a92c990000000b00325b96e6701mr5209574iln.2.1685636698083; Thu, 01 Jun 2023 09:24:58 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:57 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 36/40] expo: Add spacing around menus and items Date: Thu, 1 Jun 2023 10:23:00 -0600 Message-ID: <20230601162404.220488-35-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean It looks better if menus have a bit of an inset, rather than be drawn hard up against the background. Also, menu items look better if they have a bit of spacing between them. Add theme options for these and implement the required changes. Signed-off-by: Simon Glass --- arch/sandbox/dts/test.dts | 2 ++ boot/expo.c | 2 ++ boot/scene.c | 6 ++++-- boot/scene_menu.c | 37 ++++++++++++++++++++++++------------- doc/develop/expo.rst | 6 ++++++ 5 files changed, 38 insertions(+), 15 deletions(-) diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index ff9f9222e6f9..38d5739421f6 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -96,6 +96,8 @@ theme { font-size = <30>; + menu-inset = <3>; + menuitem-gap-y = <1>; }; /* diff --git a/boot/expo.c b/boot/expo.c index e99555163ca4..8c6fbc0e30bc 100644 --- a/boot/expo.c +++ b/boot/expo.c @@ -254,6 +254,8 @@ int expo_apply_theme(struct expo *exp, ofnode node) memset(theme, '\0', sizeof(struct expo_theme)); ofnode_read_u32(node, "font-size", &theme->font_size); + ofnode_read_u32(node, "menu-inset", &theme->menu_inset); + ofnode_read_u32(node, "menuitem-gap-y", &theme->menuitem_gap_y); list_for_each_entry(scn, &exp->scene_head, sibling) { ret = scene_apply_theme(scn, theme); diff --git a/boot/scene.c b/boot/scene.c index ea94b90584ee..6fbc1fc578c2 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -309,6 +309,7 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode) { struct scene *scn = obj->scene; struct expo *exp = scn->expo; + const struct expo_theme *theme = &exp->theme; struct udevice *dev = exp->display; struct udevice *cons = text_mode ? NULL : exp->cons; int x, y, ret; @@ -363,8 +364,9 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode) vid_priv = dev_get_uclass_priv(dev); if (obj->flags & SCENEOF_POINT) { vidconsole_push_colour(cons, fore, back, &old); - video_fill_part(dev, x, y, - x + obj->dim.w, y + obj->dim.h, + video_fill_part(dev, x - theme->menu_inset, y, + x + obj->dim.w, + y + obj->dim.h, vid_priv->colour_bg); } vidconsole_set_cursor_pos(cons, x, y); diff --git a/boot/scene_menu.c b/boot/scene_menu.c index dfe5692d6ce7..8a355f838cc8 100644 --- a/boot/scene_menu.c +++ b/boot/scene_menu.c @@ -98,7 +98,7 @@ static void menu_point_to_item(struct scene_obj_menu *menu, uint item_id) update_pointers(menu, item_id, true); } -static int scene_bbox_union(struct scene *scn, uint id, +static int scene_bbox_union(struct scene *scn, uint id, int inset, struct vidconsole_bbox *bbox) { struct scene_obj *obj; @@ -109,14 +109,14 @@ static int scene_bbox_union(struct scene *scn, uint id, if (!obj) return log_msg_ret("obj", -ENOENT); if (bbox->valid) { - bbox->x0 = min(bbox->x0, obj->dim.x); + bbox->x0 = min(bbox->x0, obj->dim.x - inset); bbox->y0 = min(bbox->y0, obj->dim.y); - bbox->x1 = max(bbox->x1, obj->dim.x + obj->dim.w); + bbox->x1 = max(bbox->x1, obj->dim.x + obj->dim.w + inset); bbox->y1 = max(bbox->y1, obj->dim.y + obj->dim.h); } else { - bbox->x0 = obj->dim.x; + bbox->x0 = obj->dim.x - inset; bbox->y0 = obj->dim.y; - bbox->x1 = obj->dim.x + obj->dim.w; + bbox->x1 = obj->dim.x + obj->dim.w + inset; bbox->y1 = obj->dim.y + obj->dim.h; bbox->valid = true; } @@ -135,22 +135,31 @@ static void scene_menu_calc_bbox(struct scene_obj_menu *menu, struct vidconsole_bbox *bbox, struct vidconsole_bbox *label_bbox) { + const struct expo_theme *theme = &menu->obj.scene->expo->theme; const struct scene_menitem *item; bbox->valid = false; - scene_bbox_union(menu->obj.scene, menu->title_id, bbox); + scene_bbox_union(menu->obj.scene, menu->title_id, 0, bbox); label_bbox->valid = false; list_for_each_entry(item, &menu->item_head, sibling) { - scene_bbox_union(menu->obj.scene, item->label_id, bbox); - scene_bbox_union(menu->obj.scene, item->key_id, bbox); - scene_bbox_union(menu->obj.scene, item->desc_id, bbox); - scene_bbox_union(menu->obj.scene, item->preview_id, bbox); + scene_bbox_union(menu->obj.scene, item->label_id, + theme->menu_inset, bbox); + scene_bbox_union(menu->obj.scene, item->key_id, 0, bbox); + scene_bbox_union(menu->obj.scene, item->desc_id, 0, bbox); + scene_bbox_union(menu->obj.scene, item->preview_id, 0, bbox); /* Get the bounding box of all labels */ - scene_bbox_union(menu->obj.scene, item->label_id, label_bbox); + scene_bbox_union(menu->obj.scene, item->label_id, + theme->menu_inset, label_bbox); } + + /* + * subtract the final menuitem's gap to keep the insert the same top + * and bottom + */ + label_bbox->y1 -= theme->menuitem_gap_y; } int scene_menu_calc_dims(struct scene_obj_menu *menu) @@ -182,6 +191,7 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu) const bool open = menu->obj.flags & SCENEOF_OPEN; struct expo *exp = scn->expo; const bool stack = exp->popup; + const struct expo_theme *theme = &exp->theme; struct scene_menitem *item; uint sel_id; int x, y; @@ -233,7 +243,8 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu) * Put the label on the left, then leave a space for the * pointer, then the key and the description */ - ret = scene_obj_set_pos(scn, item->label_id, x, y); + ret = scene_obj_set_pos(scn, item->label_id, + x + theme->menu_inset, y); if (ret < 0) return log_msg_ret("nam", ret); scene_obj_set_hide(scn, item->label_id, @@ -269,7 +280,7 @@ int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu) } if (!stack || open) - y += height; + y += height + theme->menuitem_gap_y; } if (sel_id) diff --git a/doc/develop/expo.rst b/doc/develop/expo.rst index 80e435c5e65e..bd593dc2b3f5 100644 --- a/doc/develop/expo.rst +++ b/doc/develop/expo.rst @@ -162,6 +162,12 @@ properties: font-size Font size to use for all text (type: u32) +menu-inset + Number of pixels to inset the menu on the sides and top (type: u32) + +menuitem-gap-y + Number of pixels between menu items + API documentation ----------------- From patchwork Thu Jun 1 16:23:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789264 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=Khzb89+M; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBWZ4W9xz20QH for ; Fri, 2 Jun 2023 02:32:58 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 7D38E865F6; Thu, 1 Jun 2023 18:26:42 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="Khzb89+M"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 488DB8634D; Thu, 1 Jun 2023 18:25:32 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x135.google.com (mail-il1-x135.google.com [IPv6:2607:f8b0:4864:20::135]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id E0EAD863A0 for ; Thu, 1 Jun 2023 18:25:25 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x135.google.com with SMTP id e9e14a558f8ab-33b1e83e204so3996075ab.1 for ; Thu, 01 Jun 2023 09:25:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636699; x=1688228699; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ifFCP9Gs3YCmtyt9qElj2KC66zIvKSToP001vjnzG/0=; b=Khzb89+M7nDkRHgkl+owOA0NuQK/8MkAJ/hiStca/ohlKaFXJSxbu2VNFMU+nfCG+u EUC+wCY0uTxJs7/rt7nXncqvx1Ch9DL0AMPkNSIGvmtA647kjCxVfb4VT/f71OtH7U3J NnC61ovxyzSCsw9RJGwGHfYn2bJ5uMebg4sQI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636699; x=1688228699; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ifFCP9Gs3YCmtyt9qElj2KC66zIvKSToP001vjnzG/0=; b=M5GQsVRnysfydSuHg08AwCX9zDVRgPsyesKQQDhpdKdYB7PLslKALJGimx6Ro9NBO+ 5cyMAkaWODwSTGJj07AImqTwPf8V/sGuUxV7ZCwlnExBMvWAVz+3I9WeoIZbasZRbdGv abmMtoMhopL/EyikSI5ZuHfu86Hep3eEMzy9FU3k2pX2YKe2NVUlfioM6NJG8cvgIPe6 QwN1h2PCRs2yoT9g+V8ITeEqkpmK9c1dQ+oUqTSjdWNDPn+BRGQQvo4paXM5pn3QmsJ/ jpx+Is3a79fnrwZ9MyPPcW1cM5a+aX0FYRdK7eIy+XF8H4mczU8Q80iFNlbWjOhp9ikh oh4g== X-Gm-Message-State: AC+VfDxlcLdpoZwrnVjIWXridyBRFD9qzsKgrm3qT4+24mAbCGjMEQN/ LA97D0okaECIiw0+uf7NCDsk7y5pbubtPEwZuAw= X-Google-Smtp-Source: ACHHUZ4em9cNnexzB5k75hM1zCnfxY1V0NpBt3LWAIXa14PFMtAsQvmdkA7ekvzoFmbCBkI7ZVYCSw== X-Received: by 2002:a05:6e02:54c:b0:335:c544:a1a7 with SMTP id i12-20020a056e02054c00b00335c544a1a7mr6665155ils.0.1685636698919; Thu, 01 Jun 2023 09:24:58 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:58 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 37/40] expo: Support building an expo from a description file Date: Thu, 1 Jun 2023 10:23:01 -0600 Message-ID: <20230601162404.220488-36-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean The only way to create an expo at present is by calling the functions to create each object. It is useful to have more data-driven approach, where the objects can be specified in a suitable file format and created from that. This makes testing easier as well. Add support for describing an expo in a devicetree node. This allows more complex tests to be set up, as well as providing an easier format for users. It also provides a better basis for the upcoming configuration editor. Signed-off-by: Simon Glass --- arch/sandbox/dts/cedit.dtsi | 64 ++++++ arch/sandbox/dts/test.dts | 5 + boot/Makefile | 2 +- boot/expo.c | 1 + boot/expo_build.c | 400 ++++++++++++++++++++++++++++++++++++ doc/develop/expo.rst | 282 ++++++++++++++++++++++++- include/expo.h | 14 ++ include/test/cedit-test.h | 29 +++ test/boot/expo.c | 80 ++++++++ 9 files changed, 870 insertions(+), 7 deletions(-) create mode 100644 arch/sandbox/dts/cedit.dtsi create mode 100644 boot/expo_build.c create mode 100644 include/test/cedit-test.h diff --git a/arch/sandbox/dts/cedit.dtsi b/arch/sandbox/dts/cedit.dtsi new file mode 100644 index 000000000000..a9eb4c2d594a --- /dev/null +++ b/arch/sandbox/dts/cedit.dtsi @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Expo definition for the configuration editor + * + * This used for testing building an expo from a data file. This devicetree + * provides a description of the objects to be created. + */ + +#include + +&cedit { + dynamic-start = ; + + scenes { + main { + id = ; + + /* value refers to the matching id in /strings */ + title-id = ; + + /* simple string is used as it is */ + prompt = "UP and DOWN to choose, ENTER to select"; + + /* defines a menu within the scene */ + cpu-speed { + type = "menu"; + id = ; + + /* + * has both string and ID. The string is ignored + * if the ID is present and points to a string + */ + title = "CPU speed"; + title-id = ; + + /* menu items as simple strings */ + item-label = "2 GHz", "2.5 GHz", "3 GHz"; + + /* IDs for the menu items */ + item-id = ; + }; + + power-loss { + type = "menu"; + id = ; + + title = "AC Power"; + item-label = "Always Off", "Always On", + "Memory"; + + item-id = ; + }; + }; + }; + + strings { + title { + id = ; + value = "Test Configuration"; + value-es = "configuración de prueba"; + }; + }; +}; diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 38d5739421f6..442222e4b995 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -141,6 +141,9 @@ }; }; + cedit: cedit { + }; + fuzzing-engine { compatible = "sandbox,fuzzing-engine"; }; @@ -1830,3 +1833,5 @@ #ifdef CONFIG_SANDBOX_VPL #include "sandbox_vpl.dtsi" #endif + +#include "cedit.dtsi" diff --git a/boot/Makefile b/boot/Makefile index f94c31d922de..28c4e55ca656 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -50,7 +50,7 @@ ifdef CONFIG_SPL_BUILD obj-$(CONFIG_SPL_LOAD_FIT) += common_fit.o endif -obj-$(CONFIG_$(SPL_TPL_)EXPO) += expo.o scene.o scene_menu.o +obj-$(CONFIG_$(SPL_TPL_)EXPO) += expo.o scene.o scene_menu.o expo_build.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE) += vbe.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE_REQUEST) += vbe_request.o diff --git a/boot/expo.c b/boot/expo.c index 8c6fbc0e30bc..db837f7b4924 100644 --- a/boot/expo.c +++ b/boot/expo.c @@ -58,6 +58,7 @@ void expo_destroy(struct expo *exp) uint resolve_id(struct expo *exp, uint id) { + log_debug("resolve id %d\n", id); if (!id) id = exp->next_id++; else if (id >= exp->next_id) diff --git a/boot/expo_build.c b/boot/expo_build.c new file mode 100644 index 000000000000..7e61ab06a8da --- /dev/null +++ b/boot/expo_build.c @@ -0,0 +1,400 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Building an expo from an FDT description + * + * Copyright 2022 Google LLC + * Written by Simon Glass + */ + +#define LOG_CATEGORY LOGC_EXPO + +#include +#include +#include +#include +#include +#include +#include + +/** + * struct build_info - Information to use when building + * + * @str_for_id: String for each ID in use, NULL if empty. The string is NULL + * if there is nothing for this ID. Since ID 0 is never used, the first + * element of this array is always NULL + * @str_count: Number of entries in @str_for_id + */ +struct build_info { + const char **str_for_id; + int str_count; +}; + +/** + * add_txt_str - Add a string or lookup its ID, then add to expo + * + * @info: Build information + * @node: Node describing scene + * @scn: Scene to add to + * @find_name: Name to look for (e.g. "title"). This will find a property called + * "title" if it exists, else will look up the string for "title-id" + * Return: ID of added string, or -ve on error + */ +int add_txt_str(struct build_info *info, ofnode node, struct scene *scn, + const char *find_name, uint obj_id) +{ + const char *text; + uint str_id; + int ret; + + text = ofnode_read_string(node, find_name); + if (!text) { + char name[40]; + u32 id; + + snprintf(name, sizeof(name), "%s-id", find_name); + ret = ofnode_read_u32(node, name, &id); + if (ret) + return log_msg_ret("id", -EINVAL); + + if (id >= info->str_count) + return log_msg_ret("id", -E2BIG); + text = info->str_for_id[id]; + if (!text) + return log_msg_ret("id", -EINVAL); + } + + ret = expo_str(scn->expo, find_name, 0, text); + if (ret < 0) + return log_msg_ret("add", ret); + str_id = ret; + + ret = scene_txt_str(scn, find_name, obj_id, str_id, text, NULL); + if (ret < 0) + return log_msg_ret("add", ret); + + return ret; +} + +/** + * add_txt_str_list - Add a list string or lookup its ID, then add to expo + * + * @info: Build information + * @node: Node describing scene + * @scn: Scene to add to + * @find_name: Name to look for (e.g. "title"). This will find a string-list + * property called "title" if it exists, else will look up the string in the + * "title-id" string list. + * Return: ID of added string, or -ve on error + */ +int add_txt_str_list(struct build_info *info, ofnode node, struct scene *scn, + const char *find_name, int index, uint obj_id) +{ + const char *text; + uint str_id; + int ret; + + ret = ofnode_read_string_index(node, find_name, index, &text); + if (ret) { + char name[40]; + u32 id; + + snprintf(name, sizeof(name), "%s-id", find_name); + ret = ofnode_read_u32_index(node, name, index, &id); + if (ret) + return log_msg_ret("id", -ENOENT); + + if (id >= info->str_count) + return log_msg_ret("id", -E2BIG); + text = info->str_for_id[id]; + if (!text) + return log_msg_ret("id", -EINVAL); + } + + ret = expo_str(scn->expo, find_name, 0, text); + if (ret < 0) + return log_msg_ret("add", ret); + str_id = ret; + + ret = scene_txt_str(scn, find_name, obj_id, str_id, text, NULL); + if (ret < 0) + return log_msg_ret("add", ret); + + return ret; +} + +/* + * build_element() - Handle creating a text object from a label + * + * Look up a property called @label or @label-id and create a string for it + */ +int build_element(void *ldtb, int node, const char *label) +{ + return 0; +} + +/** + * read_strings() - Read in the list of strings + * + * Read the strings into an ID-indexed list, so they can be used for building + * an expo. The strings are in a /strings node and each has its own subnode + * containing the ID and the string itself: + * + * example { + * id = <123>; + * value = "This is a test"; + * }; + * + * Future work may add support for unicode and multiple languages + * + * @info: Build information + * @root: Root node to read from + * Returns: 0 if OK, -ENOMEM if out of memory, -EINVAL if there is a format + * error + */ +static int read_strings(struct build_info *info, ofnode root) +{ + ofnode strings, node; + + strings = ofnode_find_subnode(root, "strings"); + if (!ofnode_valid(strings)) + return log_msg_ret("str", -EINVAL); + + ofnode_for_each_subnode(node, strings) { + const char *val; + int ret; + u32 id; + + ret = ofnode_read_u32(node, "id", &id); + if (ret) + return log_msg_ret("id", -EINVAL); + val = ofnode_read_string(node, "value"); + if (!val) + return log_msg_ret("val", -EINVAL); + + if (id >= info->str_count) { + int new_count = info->str_count + 20; + void *new_arr; + + new_arr = realloc(info->str_for_id, + new_count * sizeof(char *)); + if (!new_arr) + return log_msg_ret("id", -ENOMEM); + memset(new_arr + info->str_count, '\0', + (new_count - info->str_count) * sizeof(char *)); + info->str_for_id = new_arr; + info->str_count = new_count; + } + + info->str_for_id[id] = val; + } + + return 0; +} + +/** + * list_strings() - List the available strings with their IDs + * + * @info: Build information + */ +static void list_strings(struct build_info *info) +{ + int i; + + for (i = 0; i < info->str_count; i++) { + if (info->str_for_id[i]) + printf("%3d %s\n", i, info->str_for_id[i]); + } +} + +/** + * menu_build() - Build a menu and add it to a scene + * + * See doc/developer/expo.rst for a description of the format + * + * @info: Build information + * @node: Node containing the menu description + * @scn: Scene to add the menu to + * Returns: 0 if OK, -ENOMEM if out of memory, -EINVAL if there is a format + * error, -ENOENT if there is a references to a non-existent string + */ +static int menu_build(struct build_info *info, ofnode node, struct scene *scn) +{ + struct scene_obj_menu *menu; + uint title_id, menu_id; + const u32 *item_ids; + int ret, size, i; + const char *name; + u32 id; + + name = ofnode_get_name(node); + ret = ofnode_read_u32(node, "id", &id); + if (ret) + return log_msg_ret("id", -EINVAL); + + ret = scene_menu(scn, name, id, &menu); + if (ret < 0) + return log_msg_ret("men", ret); + menu_id = ret; + + /* Set the title */ + ret = add_txt_str(info, node, scn, "title", 0); + if (ret < 0) + return log_msg_ret("tit", ret); + title_id = ret; + ret = scene_menu_set_title(scn, menu_id, title_id); + + item_ids = ofnode_read_prop(node, "item-id", &size); + if (!item_ids) + return log_msg_ret("itm", -EINVAL); + if (!size || size % sizeof(u32)) + return log_msg_ret("isz", -EINVAL); + size /= sizeof(u32); + + for (i = 0; i < size; i++) { + struct scene_menitem *item; + uint label, key, desc; + + ret = add_txt_str_list(info, node, scn, "item-label", i, 0); + if (ret < 0 && ret != -ENOENT) + return log_msg_ret("lab", ret); + label = max(0, ret); + + ret = add_txt_str_list(info, node, scn, "key-label", i, 0); + if (ret < 0 && ret != -ENOENT) + return log_msg_ret("key", ret); + key = max(0, ret); + + ret = add_txt_str_list(info, node, scn, "desc-label", i, 0); + if (ret < 0 && ret != -ENOENT) + return log_msg_ret("lab", ret); + desc = max(0, ret); + + ret = scene_menuitem(scn, menu_id, simple_xtoa(i), + fdt32_to_cpu(item_ids[i]), key, label, + desc, 0, 0, &item); + if (ret < 0) + return log_msg_ret("mi", ret); + } + + return 0; +} + +/** + * menu_build() - Build an expo object and add it to a scene + * + * See doc/developer/expo.rst for a description of the format + * + * @info: Build information + * @node: Node containing the object description + * @scn: Scene to add the object to + * Returns: 0 if OK, -ENOMEM if out of memory, -EINVAL if there is a format + * error, -ENOENT if there is a references to a non-existent string + */ +static int obj_build(struct build_info *info, ofnode node, struct scene *scn) +{ + const char *type; + u32 id; + int ret; + + log_debug("- object %s\n", ofnode_get_name(node)); + ret = ofnode_read_u32(node, "id", &id); + if (ret) + return log_msg_ret("id", -EINVAL); + + type = ofnode_read_string(node, "type"); + if (!type) + return log_msg_ret("typ", -EINVAL); + + if (!strcmp("menu", type)) + ret = menu_build(info, node, scn); + else + ret = -EINVAL; + if (ret) + return log_msg_ret("bld", ret); + + return 0; +} + +/** + * scene_build() - Build a scene and all its objects + * + * See doc/developer/expo.rst for a description of the format + * + * @info: Build information + * @node: Node containing the scene description + * @scn: Scene to add the object to + * Returns: 0 if OK, -ENOMEM if out of memory, -EINVAL if there is a format + * error, -ENOENT if there is a references to a non-existent string + */ +static int scene_build(struct build_info *info, ofnode scn_node, + struct expo *exp) +{ + const char *name; + struct scene *scn; + uint id, title_id; + ofnode node; + int ret; + + name = ofnode_get_name(scn_node); + log_debug("Building scene %s\n", name); + ret = ofnode_read_u32(scn_node, "id", &id); + if (ret) + return log_msg_ret("id", -EINVAL); + + ret = scene_new(exp, name, id, &scn); + if (ret < 0) + return log_msg_ret("scn", ret); + + ret = add_txt_str(info, scn_node, scn, "title", 0); + if (ret < 0) + return log_msg_ret("tit", ret); + title_id = ret; + scene_title_set(scn, title_id); + + ret = add_txt_str(info, scn_node, scn, "prompt", 0); + if (ret < 0) + return log_msg_ret("pr", ret); + + ofnode_for_each_subnode(node, scn_node) { + ret = obj_build(info, node, scn); + if (ret < 0) + return log_msg_ret("mit", ret); + } + + return 0; +} + +int expo_build(ofnode root, struct expo **expp) +{ + struct build_info info; + ofnode scenes, node; + struct expo *exp; + u32 dyn_start; + int ret; + + memset(&info, '\0', sizeof(info)); + ret = read_strings(&info, root); + if (ret) + return log_msg_ret("str", ret); + list_strings(&info); + + ret = expo_new("name", NULL, &exp); + if (ret) + return log_msg_ret("exp", ret); + + if (!ofnode_read_u32(root, "dynamic-start", &dyn_start)) + expo_set_dynamic_start(exp, dyn_start); + + scenes = ofnode_find_subnode(root, "scenes"); + if (!ofnode_valid(scenes)) + return log_msg_ret("sno", -EINVAL); + + ofnode_for_each_subnode(node, scenes) { + ret = scene_build(&info, node, exp); + if (ret < 0) + return log_msg_ret("scn", ret); + } + *expp = exp; + + return 0; +} diff --git a/doc/develop/expo.rst b/doc/develop/expo.rst index bd593dc2b3f5..f5caadbfd98c 100644 --- a/doc/develop/expo.rst +++ b/doc/develop/expo.rst @@ -100,10 +100,13 @@ objects first, then create the menu item, passing in the relevant IDs. Creating an expo ---------------- -To create an expo, use `expo_new()` followed by `scene_new()` to create a scene. -Then add objects to the scene, using functions like `scene_txt_str()` and -`scene_menu()`. For every menu item, add text and image objects, then create -the menu item with `scene_menuitem()`, referring to those objects. +To create an expo programmatically, use `expo_new()` followed by `scene_new()` +to create a scene. Then add objects to the scene, using functions like +`scene_txt_str()` and `scene_menu()`. For every menu item, add text and image +objects, then create the menu item with `scene_menuitem()`, referring to those +objects. + +To create an expo using a description file, see :ref:`expo_format` below. Layout ------ @@ -168,6 +171,273 @@ menu-inset menuitem-gap-y Number of pixels between menu items +.. _expo_format: + +Pop-up mode +----------- + +Expos support two modes. The simple mode is used for selecting from a single +menu, e.g. when choosing with OS to boot. In this mode the menu items are shown +in a list (label, > pointer, key and description) and can be chosen using arrow +keys and enter:: + + U-Boot Boot Menu + + UP and DOWN to choose, ENTER to select + + mmc1 > 0 Fedora-Workstation-armhfp-31-1.9 + mmc3 1 Armbian + +The popup mode allows multiple menus to be present in a scene. Each is shown +just as its title and label, as with the `CPU Speed` and `AC Power` menus here:: + + Test Configuration + + + CPU Speed <2 GHz> (highlighted) + + AC Power Always Off + + + UP and DOWN to choose, ENTER to select + + +Expo Format +----------- + +It can be tedious to create a complex expo using code. Expo supports a +data-driven approach, where the expo description is in a devicetree file. This +makes it easier and faster to create and edit the description. An expo builder +is provided to convert this format into an expo structure. + +Layout of the expo scenes is handled automatically, based on a set of simple +rules. + +Top-level node +~~~~~~~~~~~~~~ + +The top-level node has the following properties: + +dynamic-start + type: u32, optional + + Specifies the start of the dynamically allocated objects. This results in + a call to expo_set_dynamic_start(). + +The top-level node has the following subnodes: + +scenes + Specifies the scenes in the expo, each one being a subnode + +strings + Specifies the strings in the expo, each one being a subnode + +`scenes` node +~~~~~~~~~~~~~ + +Contains a list of scene subnodes. The name of each subnode is passed as the +name to `scene_new()`. + +`strings` node +~~~~~~~~~~~~~~ + +Contains a list of string subnodes. The name of each subnode is ignored. + +`strings` subnodes +~~~~~~~~~~~~~~~~~~ + +Each subnode defines a string which can be used by scenes and objects. Each +string has an ID number which is used to refer to it. + +The `strings` subnodes have the following properties: + +id + type: u32, required + + Specifies the ID number for the string. + +value: + type: string, required + + Specifies the string text. For now only a single value is supported. Future + work may add support for multiple languages by using a value for each + language. + +Scene nodes (`scenes` subnodes) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Each subnode of the `scenes` node contains a scene description. + +Most properties can use either a string or a string ID. For example, a `title` +property can be used to provide the title for a menu; alternatively a `title-id` +property can provide the string ID of the title. If both are present, the +ID takes preference, except that if a string with that ID does not exist, it +falls back to using the string from the property (`title` in this example). The +description below shows these are alternative properties with the same +description. + +The scene nodes have the following properties: + +id + type: u32, required + + Specifies the ID number for the string. + +title / title-id + type: string / u32, required + + Specifies the title of the scene. This is shown at the top of the scene. + +prompt / prompt-id + type: string / u32, required + + Specifies a prompt for the scene. This is shown at the bottom of the scene. + +The scene nodes have a subnode for each object in the scene. + +Object nodes +~~~~~~~~~~~~ + +The object-node name is used as the name of the object, e.g. when calling +`scene_menu()` to create a menu. + +Object nodes have the following common properties: + +type + type: string, required + + Specifies the type of the object. Valid types are: + + "menu" + Menu containing items which can be selected by the user + +id + type: u32, required + + Specifies the ID of the object. This is used when referring to the object. + + +Menu nodes have the following additional properties: + +title / title-id + type: string / u32, required + + Specifies the title of the menu. This is shown to the left of the area for + this menu. + +item-id + type: u32 list, required + + Specifies the ID for each menu item. These are used for checking which item + has been selected. + +item-label / item-label-id + type: string list / u32 list, required + + Specifies the label for each item in the menu. These are shown to the user. + In 'popup' mode these form the items in the menu. + +key-label / key-label-id + type: string list / u32 list, optional + + Specifies the key for each item in the menu. These are currently only + intended for use in simple mode. + +desc-label / desc-label-id + type: string list / u32 list, optional + + Specifies the description for each item in the menu. These are currently + only intended for use in simple mode. + + +Expo layout +~~~~~~~~~~~ + +The `expo_arrange()` function can be called to arrange the expo objects in a +suitable manner. For each scene it puts the title at the top, the prompt at the +bottom and the objects in order from top to bottom. + +Expo format example +~~~~~~~~~~~~~~~~~~~ + +This example shows an expo with a single scene consisting of two menus. The +scene title is specified using a string from the strings table, but all other +strings are provided inline in the nodes where they are used. + +:: + + #define ID_PROMPT 1 + #define ID_SCENE1 2 + #define ID_SCENE1_TITLE 3 + + #define ID_CPU_SPEED 4 + #define ID_CPU_SPEED_TITLE 5 + #define ID_CPU_SPEED_1 6 + #define ID_CPU_SPEED_2 7 + #define ID_CPU_SPEED_3 8 + + #define ID_POWER_LOSS 9 + #define ID_AC_OFF 10 + #define ID_AC_ON 11 + #define ID_AC_MEMORY 12 + + #define ID_DYNAMIC_START 13 + + &cedit { + dynamic-start = ; + + scenes { + main { + id = ; + + /* value refers to the matching id in /strings */ + title-id = ; + + /* simple string is used as it is */ + prompt = "UP and DOWN to choose, ENTER to select"; + + /* defines a menu within the scene */ + cpu-speed { + type = "menu"; + id = ; + + /* + * has both string and ID. The string is ignored + * if the ID is present and points to a string + */ + title = "CPU speed"; + title-id = ; + + /* menu items as simple strings */ + item-label = "2 GHz", "2.5 GHz", "3 GHz"; + + /* IDs for the menu items */ + item-id = ; + }; + + power-loss { + type = "menu"; + id = ; + + title = "AC Power"; + item-label = "Always Off", "Always On", + "Memory"; + + item-id = ; + }; + }; + }; + + strings { + title { + id = ; + value = "Test Configuration"; + value-es = "configuración de prueba"; + }; + }; + }; + API documentation ----------------- @@ -180,11 +450,10 @@ Future ideas Some ideas for future work: - Default menu item and a timeout -- Higher-level / automatic / more flexible layout of objects - Image formats other than BMP - Use of ANSI sequences to control a serial terminal - Colour selection -- Better support for handling lots of settings, e.g. with radio/option widgets +- Support for more widgets, e.g. text, numeric, radio/option - Mouse support - Integrate Nuklear, NxWidgets or some other library for a richer UI - Optimise rendering by only updating the display with changes since last render @@ -194,6 +463,7 @@ Some ideas for future work: - Support both graphical and text menus at the same time on different devices - Support unicode - Support curses for proper serial-terminal menus +- Add support for large menus which need to scroll .. Simon Glass .. 7-Oct-22 diff --git a/include/expo.h b/include/expo.h index f7febe1c9ae7..9fec4d0cd84e 100644 --- a/include/expo.h +++ b/include/expo.h @@ -653,4 +653,18 @@ int expo_action_get(struct expo *exp, struct expo_action *act); */ int expo_apply_theme(struct expo *exp, ofnode node); +/** + * expo_build() - Build an expo from an FDT description + * + * Build a complete expo from a description in the provided devicetree. + * + * See doc/developer/expo.rst for a description of the format + * + * @root: Root node for expo description + * @expp: Returns the new expo + * Returns: 0 if OK, -ENOMEM if out of memory, -EINVAL if there is a format + * error, -ENOENT if there is a references to a non-existent string + */ +int expo_build(ofnode root, struct expo **expp); + #endif /*__SCENE_H */ diff --git a/include/test/cedit-test.h b/include/test/cedit-test.h new file mode 100644 index 000000000000..349df75b16d4 --- /dev/null +++ b/include/test/cedit-test.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Binding shared between cedit.dtsi and test/boot/expo.c + * + * Copyright 2023 Google LLC + * Written by Simon Glass + */ + +#ifndef __cedit_test_h +#define __cedit_test_h + +#define ID_PROMPT 1 +#define ID_SCENE1 2 +#define ID_SCENE1_TITLE 3 + +#define ID_CPU_SPEED 4 +#define ID_CPU_SPEED_TITLE 5 +#define ID_CPU_SPEED_1 6 +#define ID_CPU_SPEED_2 7 +#define ID_CPU_SPEED_3 8 + +#define ID_POWER_LOSS 9 +#define ID_AC_OFF 10 +#define ID_AC_ON 11 +#define ID_AC_MEMORY 12 + +#define ID_DYNAMIC_START 13 + +#endif diff --git a/test/boot/expo.c b/test/boot/expo.c index c34eaeedd66f..e7148024fe30 100644 --- a/test/boot/expo.c +++ b/test/boot/expo.c @@ -13,6 +13,7 @@ #include #include #include "bootstd_common.h" +#include #include "../../boot/scene_internal.h" enum { @@ -588,3 +589,82 @@ static int expo_render_image(struct unit_test_state *uts) return 0; } BOOTSTD_TEST(expo_render_image, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check building an expo from a devicetree description */ +static int expo_test_build(struct unit_test_state *uts) +{ + struct scene_obj_menu *menu; + struct scene_menitem *item; + struct scene_obj_txt *txt; + struct scene_obj *obj; + struct scene *scn; + struct expo *exp; + int count; + ofnode node; + + node = ofnode_path("/cedit"); + ut_assert(ofnode_valid(node)); + ut_assertok(expo_build(node, &exp)); + + ut_asserteq_str("name", exp->name); + ut_asserteq(0, exp->scene_id); + ut_asserteq(ID_DYNAMIC_START + 20, exp->next_id); + ut_asserteq(false, exp->popup); + + /* check the scene */ + scn = expo_lookup_scene_id(exp, ID_SCENE1); + ut_assertnonnull(scn); + ut_asserteq_str("main", scn->name); + ut_asserteq(ID_SCENE1, scn->id); + ut_asserteq(ID_DYNAMIC_START + 1, scn->title_id); + ut_asserteq(0, scn->highlight_id); + + /* check the title */ + txt = scene_obj_find(scn, scn->title_id, SCENEOBJT_NONE); + ut_assertnonnull(txt); + obj = &txt->obj; + ut_asserteq_ptr(scn, obj->scene); + ut_asserteq_str("title", obj->name); + ut_asserteq(scn->title_id, obj->id); + ut_asserteq(SCENEOBJT_TEXT, obj->type); + ut_asserteq(0, obj->flags); + ut_asserteq_str("Test Configuration", expo_get_str(exp, txt->str_id)); + + /* check the menu */ + menu = scene_obj_find(scn, ID_CPU_SPEED, SCENEOBJT_NONE); + obj = &menu->obj; + ut_asserteq_ptr(scn, obj->scene); + ut_asserteq_str("cpu-speed", obj->name); + ut_asserteq(ID_CPU_SPEED, obj->id); + ut_asserteq(SCENEOBJT_MENU, obj->type); + ut_asserteq(0, obj->flags); + + txt = scene_obj_find(scn, menu->title_id, SCENEOBJT_NONE); + ut_asserteq_str("CPU speed", expo_get_str(exp, txt->str_id)); + + ut_asserteq(0, menu->cur_item_id); + ut_asserteq(0, menu->pointer_id); + + /* check the items */ + item = list_first_entry(&menu->item_head, struct scene_menitem, + sibling); + ut_asserteq_str("00", item->name); + ut_asserteq(ID_CPU_SPEED_1, item->id); + ut_asserteq(0, item->key_id); + ut_asserteq(0, item->desc_id); + ut_asserteq(0, item->preview_id); + ut_asserteq(0, item->flags); + + txt = scene_obj_find(scn, item->label_id, SCENEOBJT_NONE); + ut_asserteq_str("2 GHz", expo_get_str(exp, txt->str_id)); + + count = 0; + list_for_each_entry(item, &menu->item_head, sibling) + count++; + ut_asserteq(3, count); + + expo_destroy(exp); + + return 0; +} +BOOTSTD_TEST(expo_test_build, UT_TESTF_DM); From patchwork Thu Jun 1 16:23:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789267 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=kKqI60C6; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBWt699jz20QH for ; Fri, 2 Jun 2023 02:33:14 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 57E8A865F0; Thu, 1 Jun 2023 18:26:44 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="kKqI60C6"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 9DFDE865B7; Thu, 1 Jun 2023 18:25:42 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x133.google.com (mail-il1-x133.google.com [IPv6:2607:f8b0:4864:20::133]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 900988634D for ; Thu, 1 Jun 2023 18:25:35 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x133.google.com with SMTP id e9e14a558f8ab-33b3f2f7989so3489235ab.0 for ; Thu, 01 Jun 2023 09:25:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636700; x=1688228700; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=5QgIdt/EwxPxA+/zQ2C8UjH0SDWGYYPobOh1Cht9MAE=; b=kKqI60C6h2/sx+7f9WgXYWJ1yqVC/uVf6rKog+ZF++Bb8nKovzZ0RLQsGCXa2Y4rdT yelvpcv6ia/AkRCiNiDTguUcQ3zQKPYhDRx1u6qlHXQsCpaKFuRppRSnNuQLptcYKPhH SC2AsHIfaq3Pddl7Q1Jr8jV2x+CUmokWzaH/k= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636700; x=1688228700; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=5QgIdt/EwxPxA+/zQ2C8UjH0SDWGYYPobOh1Cht9MAE=; b=T6StVP38ZB7H62attP9retHS0Ef9MkL297of58CRoiUlZGa6RTml98PniHnGvj7aVe xad8JL+0V2NFqNI8bkQbRFHyIAbM8qg40Wfa+9MWV/XQ8hEBciJ3lYOIIupHxx/7EqGe vavaawG6aQ+BfjzytivisrCzW+ljq5vJqgGcCAOB+/qvztd6gUPFjdJn7LwrA09r9rS1 ad7c1RNRFIA69q32kYCkeho9VFzKew58XpPRA9pAobLPKhebId/CYEsj8GQY2YiFFhq9 sXPjTVEInXXeU6dZJ9IwFuPM4q+Apmbno6u74P27hkAXo58bmkkshcMsKBkiqoiD0Tqr FQCw== X-Gm-Message-State: AC+VfDyGVx/8e5kINrovrzzKRG+h/TsMNS71UDkx9VJrzH2HQ2V4Iz8m xJMJI+DANopItpk88iWlDaQ5Xx4mlJHUDzSSamE= X-Google-Smtp-Source: ACHHUZ6ukf4sfjB9ssKvoYJMyTFleZ/aHSwKsr94CkmsdGyymildyNQhjVTh7THLIhDfVMEoRfv8ew== X-Received: by 2002:a92:cc07:0:b0:331:a813:8b17 with SMTP id s7-20020a92cc07000000b00331a8138b17mr4731825ilp.3.1685636699752; Thu, 01 Jun 2023 09:24:59 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.24.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:24:59 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 38/40] expo: Add a configuration editor Date: Thu, 1 Jun 2023 10:23:02 -0600 Message-ID: <20230601162404.220488-37-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Add a new 'cedit' command which allows editing configuration using an expo. The configuration items appear as menus on the display. This is extremely basic, only supporting menus and not providing any way to load or save the configuration. Signed-off-by: Simon Glass --- boot/Kconfig | 14 ++++ boot/Makefile | 1 + boot/cedit.c | 163 ++++++++++++++++++++++++++++++++++++++ boot/expo_build.c | 3 +- boot/scene.c | 12 +++ boot/scene_internal.h | 8 ++ cmd/Kconfig | 9 +++ cmd/Makefile | 1 + cmd/cedit.c | 93 ++++++++++++++++++++++ configs/sandbox_defconfig | 1 + doc/develop/expo.rst | 8 +- doc/usage/cmd/cedit.rst | 31 ++++++++ doc/usage/index.rst | 1 + include/expo.h | 29 +++++++ 14 files changed, 370 insertions(+), 4 deletions(-) create mode 100644 boot/cedit.c create mode 100644 cmd/cedit.c create mode 100644 doc/usage/cmd/cedit.rst diff --git a/boot/Kconfig b/boot/Kconfig index eea5ed6040ff..5385130a6e01 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -1630,4 +1630,18 @@ config SAVE_PREV_BL_INITRAMFS_START_ADDR If no initramfs was provided by previous bootloader, no env variables will be created. +menu "Configuration editor" + +config CEDIT + bool "Configuration editor" + depends on BOOTSTD + help + Provides a way to deal with board configuration and present it to + the user for adjustment. + + This is intended to provide both graphical and text-based user + interfaces, but only graphical is support at present. + +endmenu # Configuration editor + endmenu # Booting diff --git a/boot/Makefile b/boot/Makefile index 28c4e55ca656..f828f870a37b 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -33,6 +33,7 @@ ifdef CONFIG_$(SPL_TPL_)BOOTSTD_FULL obj-$(CONFIG_CMD_BOOTEFI_BOOTMGR) += bootmeth_efi_mgr.o obj-$(CONFIG_$(SPL_TPL_)EXPO) += bootflow_menu.o obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootflow_menu.o +obj-$(CONFIG_$(SPL_TPL_)CEDIT) += cedit.o endif obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o diff --git a/boot/cedit.c b/boot/cedit.c new file mode 100644 index 000000000000..ee24658917bc --- /dev/null +++ b/boot/cedit.c @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Implementation of configuration editor + * + * Copyright 2023 Google LLC + * Written by Simon Glass + */ + +#include +#include +#include +#include +#include +#include +#include +#include "scene_internal.h" + +int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id) +{ + struct scene_obj_txt *txt; + struct scene_obj *obj; + struct scene *scn; + int y; + + scn = expo_lookup_scene_id(exp, scene_id); + if (!scn) + return log_msg_ret("scn", -ENOENT); + + txt = scene_obj_find_by_name(scn, "prompt"); + if (txt) + scene_obj_set_pos(scn, txt->obj.id, 0, vpriv->ysize - 50); + + txt = scene_obj_find_by_name(scn, "title"); + if (txt) + scene_obj_set_pos(scn, txt->obj.id, 200, 10); + + y = 100; + list_for_each_entry(obj, &scn->obj_head, sibling) { + if (obj->type == SCENEOBJT_MENU) { + scene_obj_set_pos(scn, obj->id, 50, y); + scene_menu_arrange(scn, (struct scene_obj_menu *)obj); + y += 50; + } + } + + return 0; +} + +int cedit_run(struct expo *exp) +{ + struct cli_ch_state s_cch, *cch = &s_cch; + struct video_priv *vid_priv; + uint scene_id; + struct udevice *dev; + struct scene *scn; + bool done; + int ret; + + cli_ch_init(cch); + + /* For now we only support a video console */ + ret = uclass_first_device_err(UCLASS_VIDEO, &dev); + if (ret) + return log_msg_ret("vid", ret); + ret = expo_set_display(exp, dev); + if (ret) + return log_msg_ret("dis", ret); + + ret = expo_first_scene_id(exp); + if (ret < 0) + return log_msg_ret("scn", ret); + scene_id = ret; + + ret = expo_set_scene_id(exp, scene_id); + if (ret) + return log_msg_ret("sid", ret); + + exp->popup = true; + + /* This is not supported for now */ + if (0) + expo_set_text_mode(exp, true); + + vid_priv = dev_get_uclass_priv(dev); + + scn = expo_lookup_scene_id(exp, scene_id); + scene_highlight_first(scn); + + cedit_arange(exp, vid_priv, scene_id); + + ret = expo_calc_dims(exp); + if (ret) + return log_msg_ret("dim", ret); + + done = false; + do { + struct expo_action act; + int ichar, key; + + ret = expo_render(exp); + if (ret) + break; + + ichar = cli_ch_process(cch, 0); + if (!ichar) { + while (!ichar && !tstc()) { + schedule(); + mdelay(2); + ichar = cli_ch_process(cch, -ETIMEDOUT); + } + if (!ichar) { + ichar = getchar(); + ichar = cli_ch_process(cch, ichar); + } + } + + key = 0; + if (ichar) { + key = bootmenu_conv_key(ichar); + if (key == BKEY_NONE) + key = ichar; + } + if (!key) + continue; + + ret = expo_send_key(exp, key); + if (ret) + break; + + ret = expo_action_get(exp, &act); + if (!ret) { + switch (act.type) { + case EXPOACT_POINT_OBJ: + scene_set_highlight_id(scn, act.select.id); + cedit_arange(exp, vid_priv, scene_id); + break; + case EXPOACT_OPEN: + scene_set_open(scn, act.select.id, true); + cedit_arange(exp, vid_priv, scene_id); + break; + case EXPOACT_CLOSE: + scene_set_open(scn, act.select.id, false); + cedit_arange(exp, vid_priv, scene_id); + break; + case EXPOACT_SELECT: + scene_set_open(scn, scn->highlight_id, false); + cedit_arange(exp, vid_priv, scene_id); + break; + case EXPOACT_QUIT: + log_debug("quitting\n"); + done = true; + break; + default: + break; + } + } + } while (!done); + + if (ret) + return log_msg_ret("end", ret); + + return 0; +} diff --git a/boot/expo_build.c b/boot/expo_build.c index 7e61ab06a8da..22f62eb54bc5 100644 --- a/boot/expo_build.c +++ b/boot/expo_build.c @@ -376,7 +376,8 @@ int expo_build(ofnode root, struct expo **expp) ret = read_strings(&info, root); if (ret) return log_msg_ret("str", ret); - list_strings(&info); + if (_DEBUG) + list_strings(&info); ret = expo_new("name", NULL, &exp); if (ret) diff --git a/boot/scene.c b/boot/scene.c index 6fbc1fc578c2..e52333371f9c 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -92,6 +92,18 @@ void *scene_obj_find(struct scene *scn, uint id, enum scene_obj_t type) return NULL; } +void *scene_obj_find_by_name(struct scene *scn, const char *name) +{ + struct scene_obj *obj; + + list_for_each_entry(obj, &scn->obj_head, sibling) { + if (!strcmp(name, obj->name)) + return obj; + } + + return NULL; +} + int scene_obj_add(struct scene *scn, const char *name, uint id, enum scene_obj_t type, uint size, struct scene_obj **objp) { diff --git a/boot/scene_internal.h b/boot/scene_internal.h index dc98ecd02146..fb1ea5533b9a 100644 --- a/boot/scene_internal.h +++ b/boot/scene_internal.h @@ -40,6 +40,14 @@ uint resolve_id(struct expo *exp, uint id); */ void *scene_obj_find(struct scene *scn, uint id, enum scene_obj_t type); +/** + * scene_obj_find_by_name() - Find an object in a scene by name + * + * @scn: Scene to search + * @name: Name to search for + */ +void *scene_obj_find_by_name(struct scene *scn, const char *name); + /** * scene_obj_add() - Add a new object to a scene * diff --git a/cmd/Kconfig b/cmd/Kconfig index 365371fb511a..21b5550bfdf3 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -427,6 +427,15 @@ config CMD_ABOOTIMG See doc/android/boot-image.rst for details. +config CMD_CEDIT + bool "cedit - Configuration editor" + depends on CEDIT + default y + help + Provides a command to allow editing of board configuration and + providing a UI for the user to adjust settings. Subcommands allow + loading and saving of configuration as well as showing an editor. + config CMD_ELF bool "bootelf, bootvx" default y diff --git a/cmd/Makefile b/cmd/Makefile index 6c37521b4e2b..9f8c0b058bea 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -43,6 +43,7 @@ obj-$(CONFIG_CMD_BUTTON) += button.o obj-$(CONFIG_CMD_CAT) += cat.o obj-$(CONFIG_CMD_CACHE) += cache.o obj-$(CONFIG_CMD_CBFS) += cbfs.o +obj-$(CONFIG_CMD_CEDIT) += cedit.o obj-$(CONFIG_CMD_CLK) += clk.o obj-$(CONFIG_CMD_CLS) += cls.o obj-$(CONFIG_CMD_CONFIG) += config.o diff --git a/cmd/cedit.c b/cmd/cedit.c new file mode 100644 index 000000000000..0cae304c4adc --- /dev/null +++ b/cmd/cedit.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * 'cedit' command + * + * Copyright 2023 Google LLC + * Written by Simon Glass + */ + +#include +#include +#include +#include +#include +#include + +struct expo *cur_exp; + +static int do_cedit_load(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + const char *fname; + struct expo *exp; + oftree tree; + ulong size; + void *buf; + int ret; + + if (argc < 4) + return CMD_RET_USAGE; + fname = argv[3]; + + ret = fs_load_alloc(argv[1], argv[2], argv[3], SZ_1M, 0, &buf, &size); + if (ret) { + printf("File not found\n"); + return CMD_RET_FAILURE; + } + + tree = oftree_from_fdt(buf); + if (!oftree_valid(tree)) { + printf("Cannot create oftree\n"); + return CMD_RET_FAILURE; + } + + ret = expo_build(oftree_root(tree), &exp); + oftree_dispose(tree); + if (ret) { + printf("Failed to build expo: %dE\n", ret); + return CMD_RET_FAILURE; + } + + cur_exp = exp; + + return 0; +} + +static int do_cedit_run(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + ofnode node; + int ret; + + if (!cur_exp) { + printf("No expo loaded\n"); + return CMD_RET_FAILURE; + } + + node = ofnode_path("/cedit-theme"); + if (ofnode_valid(node)) { + ret = expo_apply_theme(cur_exp, node); + if (ret) + return CMD_RET_FAILURE; + } else { + log_warning("No theme found\n"); + } + ret = cedit_run(cur_exp); + if (ret) { + log_err("Failed (err=%dE)\n", ret); + return CMD_RET_FAILURE; + } + + return 0; +} + +#ifdef CONFIG_SYS_LONGHELP +static char cedit_help_text[] = + "load - load config editor\n" + "cedit run - run config editor"; +#endif /* CONFIG_SYS_LONGHELP */ + +U_BOOT_CMD_WITH_SUBCMDS(cedit, "Configuration editor", cedit_help_text, + U_BOOT_SUBCMD_MKENT(load, 5, 1, do_cedit_load), + U_BOOT_SUBCMD_MKENT(run, 1, 1, do_cedit_run), +); diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 1ec44d5b33bb..4cef6c515396 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -30,6 +30,7 @@ CONFIG_AUTOBOOT_STOP_STR_ENABLE=y CONFIG_AUTOBOOT_STOP_STR_CRYPT="$5$rounds=640000$HrpE65IkB8CM5nCL$BKT3QdF98Bo8fJpTr9tjZLZQyzqPASBY20xuK5Rent9" CONFIG_IMAGE_PRE_LOAD=y CONFIG_IMAGE_PRE_LOAD_SIG=y +CONFIG_CEDIT=y CONFIG_CONSOLE_RECORD=y CONFIG_CONSOLE_RECORD_OUT_SIZE=0x6000 CONFIG_PRE_CONSOLE_BUFFER=y diff --git a/doc/develop/expo.rst b/doc/develop/expo.rst index f5caadbfd98c..2ac4af232da4 100644 --- a/doc/develop/expo.rst +++ b/doc/develop/expo.rst @@ -171,8 +171,6 @@ menu-inset menuitem-gap-y Number of pixels between menu items -.. _expo_format: - Pop-up mode ----------- @@ -202,6 +200,8 @@ just as its title and label, as with the `CPU Speed` and `AC Power` menus here:: UP and DOWN to choose, ENTER to select +.. _expo_format: + Expo Format ----------- @@ -211,7 +211,8 @@ makes it easier and faster to create and edit the description. An expo builder is provided to convert this format into an expo structure. Layout of the expo scenes is handled automatically, based on a set of simple -rules. +rules. The :doc:`../usage/cmd/cedit` can be used to load a configuration +and create an expo from it. Top-level node ~~~~~~~~~~~~~~ @@ -464,6 +465,7 @@ Some ideas for future work: - Support unicode - Support curses for proper serial-terminal menus - Add support for large menus which need to scroll +- Add support for reading and writing configuration settings with cedit .. Simon Glass .. 7-Oct-22 diff --git a/doc/usage/cmd/cedit.rst b/doc/usage/cmd/cedit.rst new file mode 100644 index 000000000000..8e1110c7c77e --- /dev/null +++ b/doc/usage/cmd/cedit.rst @@ -0,0 +1,31 @@ +.. SPDX-License-Identifier: GPL-2.0+: + +cedit command +============= + +Synopis +------- + +:: + + cedit load + cedit run + +Description +----------- + +The *cedit* command is used to load a configuration-editor description and allow +the user to interact with it. + +It makes use of the expo subsystem. + +The description is in the form of a devicetree file, as documented at +:ref:`expo_format`. + +Example +------- + +:: + + => cedit load hostfs - fred.dtb + => cedit run diff --git a/doc/usage/index.rst b/doc/usage/index.rst index 0fde130a5480..06316e9d3118 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -37,6 +37,7 @@ Shell commands cmd/bootz cmd/cat cmd/cbsysinfo + cmd/cedit cmd/cls cmd/cmp cmd/coninfo diff --git a/include/expo.h b/include/expo.h index 9fec4d0cd84e..0b1d944a169f 100644 --- a/include/expo.h +++ b/include/expo.h @@ -11,6 +11,7 @@ #include struct udevice; +struct video_priv; /** * enum expoact_type - types of actions reported by the expo @@ -378,6 +379,14 @@ int expo_calc_dims(struct expo *exp); */ int expo_set_scene_id(struct expo *exp, uint scene_id); +/** + * expo_first_scene_id() - Get the ID of the first scene + * + * @exp: Expo to check + * Returns: Scene ID of first scene, or -ENOENT if there are no scenes + */ +int expo_first_scene_id(struct expo *exp); + /** * expo_render() - render the expo on the display / console * @@ -667,4 +676,24 @@ int expo_apply_theme(struct expo *exp, ofnode node); */ int expo_build(ofnode root, struct expo **expp); +/** + * cedit_arange() - Arrange objects in a configuration-editor scene + * + * @exp: Expo to update + * @vid_priv: Private info of the video device + * @scene_id: scene ID to arrange + * Returns: 0 if OK, -ve on error + */ +int cedit_arange(struct expo *exp, struct video_priv *vid_priv, uint scene_id); + +/** + * cedit_run() - Run a configuration editor + * + * This accepts input until the user quits with Escape + * + * @exp: Expo to use + * Returns: 0 if OK, -ve on error + */ +int cedit_run(struct expo *exp); + #endif /*__SCENE_H */ From patchwork Thu Jun 1 16:23:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789268 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=IOS1q2yb; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBX92Xr7z20QH for ; Fri, 2 Jun 2023 02:33:29 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 6802B865FB; Thu, 1 Jun 2023 18:26:46 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="IOS1q2yb"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id A8AA9865B5; Thu, 1 Jun 2023 18:25:44 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x12a.google.com (mail-il1-x12a.google.com [IPv6:2607:f8b0:4864:20::12a]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id C50DA86442 for ; Thu, 1 Jun 2023 18:25:36 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x12a.google.com with SMTP id e9e14a558f8ab-33b204f0ca0so4223655ab.2 for ; Thu, 01 Jun 2023 09:25:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636701; x=1688228701; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Kv0Q6bVKBOlQvWyjFPH+OuUw4nRh8XnZ8AvqsZRcnmk=; b=IOS1q2ybEcej4ci6vmI2ioLUnZ+KCSTYo6kQQRXrawU/Rh+f6mpb+zYDPJn+p6kcyc DlBDBAh7PdY/G3sXXEVZYpZf9KaHFIfoWkZVveXoF9Jh8G82GtIRfnPgacsqk48MPSZ8 2Y7XG0lnpjxEaassMMiLVfC2VSB2T4AUx4J3E= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636701; x=1688228701; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Kv0Q6bVKBOlQvWyjFPH+OuUw4nRh8XnZ8AvqsZRcnmk=; b=F5n+RwexNMMvmMuy20nVoKRGgg7nARAoh9fgy7AapZ5ifD6U98ORiy/yzt2KOfle4T bhNQ6l71/opt7PWoeE3roaKZ5jPfii01kirjPEilC1IBjVeN0m+JlAbucsWRBynxliNR LTAIqhDy2455fZwTYBF4gf+vsjVDts65XHIbYS2vUNIum6gowDlO/g+fFrVFA27MagwJ iigFNpelIlJUzYL2U4DNjj3nbGfbIj2v9Shp2sGR7hGgiM/M4DDOsJJ5lj52h2vL5lcq 71x/xJqYrX0Qnj/i7BGsZWvDvw7F67BeblvcQHcB+XI8SXzaClNd1VNQ/KSX0j/1btna RA3Q== X-Gm-Message-State: AC+VfDzserhInVLKjEQAEe1j9MQ0fl+yk3YQTYjjhP/j70oH4PY2+67z u7XNUVadMPh06ut8WjjG40yGyG2Igv7wLnfG62o= X-Google-Smtp-Source: ACHHUZ71qfvdfRNWZp91RO+L2HYXnkoh/9pfWaHasAwMHdz0Q8ESWAH0+l1Sf2ZL2a/09pkMkAc74A== X-Received: by 2002:a92:b106:0:b0:33a:efd3:add3 with SMTP id t6-20020a92b106000000b0033aefd3add3mr6340402ilh.14.1685636700707; Thu, 01 Jun 2023 09:25:00 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.25.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:25:00 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass Subject: [PATCH 39/40] expo: Add tests for the configuration editor Date: Thu, 1 Jun 2023 10:23:03 -0600 Message-ID: <20230601162404.220488-38-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean Add some simple tests and a helpful script to make the configuration editor easier to set up. Signed-off-by: Simon Glass --- arch/sandbox/dts/sandbox.dtsi | 6 ++ arch/sandbox/dts/test.dts | 6 ++ test/boot/expo.c | 44 +++++++++++ test/boot/files/expo_layout.dts | 84 +++++++++++++++++++++ test/py/tests/test_ut.py | 10 +++ tools/expo.py | 130 ++++++++++++++++++++++++++++++++ 6 files changed, 280 insertions(+) create mode 100644 test/boot/files/expo_layout.dts create mode 100755 tools/expo.py diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi index 30a305c4d208..f0ee0b3481ac 100644 --- a/arch/sandbox/dts/sandbox.dtsi +++ b/arch/sandbox/dts/sandbox.dtsi @@ -16,6 +16,12 @@ stdout-path = "/serial"; }; + cedit-theme { + font-size = <30>; + menu-inset = <3>; + menuitem-gap-y = <1>; + }; + alarm_wdt: alarm-wdt { compatible = "sandbox,alarm-wdt"; timeout-sec = <5>; diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 442222e4b995..b5509eee8cfe 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -144,6 +144,12 @@ cedit: cedit { }; + cedit-theme { + font-size = <30>; + menu-inset = <3>; + menuitem-gap-y = <1>; + }; + fuzzing-engine { compatible = "sandbox,fuzzing-engine"; }; diff --git a/test/boot/expo.c b/test/boot/expo.c index e7148024fe30..3898f853a751 100644 --- a/test/boot/expo.c +++ b/test/boot/expo.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -668,3 +669,46 @@ static int expo_test_build(struct unit_test_state *uts) return 0; } BOOTSTD_TEST(expo_test_build, UT_TESTF_DM); + +/* Check the cedit command */ +static int expo_cedit(struct unit_test_state *uts) +{ + extern struct expo *cur_exp; + struct scene_obj_menu *menu; + struct scene_obj_txt *txt; + struct expo *exp; + struct scene *scn; + + if (!IS_ENABLED(CONFIG_CMD_CEDIT)) + return -EAGAIN; + + ut_assertok(run_command("cedit load hostfs - cedit.dtb", 0)); + + console_record_reset_enable(); + + /* + * ^N Move down to second menu + * ^M Open menu + * ^N Move down to second item + * ^M Select item + * \e Quit + */ + console_in_puts("\x0e\x0d\x0e\x0d\e"); + ut_assertok(run_command("cedit run", 0)); + + exp = cur_exp; + scn = expo_lookup_scene_id(exp, exp->scene_id); + ut_assertnonnull(scn); + + menu = scene_obj_find(scn, scn->highlight_id, SCENEOBJT_NONE); + ut_assertnonnull(menu); + + txt = scene_obj_find(scn, menu->title_id, SCENEOBJT_NONE); + ut_assertnonnull(txt); + ut_asserteq_str("AC Power", expo_get_str(exp, txt->str_id)); + + ut_asserteq(ID_AC_ON, menu->cur_item_id); + + return 0; +} +BOOTSTD_TEST(expo_cedit, UT_TESTF_DM | UT_TESTF_SCAN_FDT); diff --git a/test/boot/files/expo_layout.dts b/test/boot/files/expo_layout.dts new file mode 100644 index 000000000000..55d5c910dd5e --- /dev/null +++ b/test/boot/files/expo_layout.dts @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Sample expo screen layout + */ + +/dts-v1/; + +/* +enum { + ZERO, + ID_PROMPT, + + ID_SCENE1, + ID_SCENE1_TITLE, + + ID_CPU_SPEED, + ID_CPU_SPEED_TITLE, + ID_CPU_SPEED_1, + ID_CPU_SPEED_2, + ID_CPU_SPEED_3, + + ID_POWER_LOSS, + ID_AC_OFF, + ID_AC_ON, + ID_AC_MEMORY, + + ID_DYNAMIC_START, +}; +*/ + +/ { + dynamic-start = ; + + scenes { + main { + id = ; + + /* value refers to the matching id in /strings */ + title-id = ; + + /* simple string is used as it is */ + prompt = "UP and DOWN to choose, ENTER to select"; + + /* defines a menu within the scene */ + cpu-speed { + type = "menu"; + id = ; + + /* + * has both string and ID. The string is ignored + * if the ID is present and points to a string + */ + title = "CPU speed"; + title-id = ; + + /* menu items as simple strings */ + item-label = "2 GHz", "2.5 GHz", "3 GHz"; + + /* IDs for the menu items */ + item-id = ; + }; + + power-loss { + type = "menu"; + id = ; + + title = "AC Power"; + item-label = "Always Off", "Always On", + "Memory"; + + item-id = ; + }; + }; + }; + + strings { + title { + id = ; + value = "Test Configuration"; + value-es = "configuración de prueba"; + }; + }; +}; diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py index 0b45863b4385..aa1d477cd565 100644 --- a/test/py/tests/test_ut.py +++ b/test/py/tests/test_ut.py @@ -282,6 +282,15 @@ label Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) copy_prepared_image(cons, mmc_dev, fname) +def setup_cedit_file(cons): + infname = os.path.join(cons.config.source_dir, + 'test/boot/files/expo_layout.dts') + expo_tool = os.path.join(cons.config.source_dir, 'tools/expo.py') + outfname = 'cedit.dtb' + u_boot_utils.run_and_log( + cons, f'{expo_tool} -e {infname} -l {infname} -o {outfname}') + + @pytest.mark.buildconfigspec('ut_dm') def test_ut_dm_init(u_boot_console): """Initialize data for ut dm tests.""" @@ -319,6 +328,7 @@ def test_ut_dm_init_bootstd(u_boot_console): setup_bootflow_image(u_boot_console) setup_bootmenu_image(u_boot_console) + setup_cedit_file(u_boot_console) # Restart so that the new mmc1.img is picked up u_boot_console.restart_uboot() diff --git a/tools/expo.py b/tools/expo.py new file mode 100755 index 000000000000..c6eb87aec739 --- /dev/null +++ b/tools/expo.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0+ + +""" +Expo utility - used for testing of expo features + +Copyright 2023 Google LLC +Written by Simon Glass +""" + +import argparse +import collections +import io +import re +import subprocess +import sys + +#from u_boot_pylib import cros_subprocess +from u_boot_pylib import tools + +# Parse: +# SCENE1 = 7, +# or SCENE2, +RE_ENUM = re.compile(r'(\S*)(\s*= (\d))?,') + +# Parse #define "string" +RE_DEF = re.compile(r'#define (\S*)\s*"(.*)"') + +def calc_ids(fname): + """Figure out the value of the enums in a C file + + Args: + fname (str): Filename to parse + + Returns: + OrderedDict(): + key (str): enum name + value (int or str): + Value of enum, if int + Value of #define, if string + """ + vals = collections.OrderedDict() + with open(fname, 'r', encoding='utf-8') as inf: + in_enum = False + cur_id = 0 + for line in inf.readlines(): + line = line.strip() + if line == 'enum {': + in_enum = True + continue + if in_enum and line == '};': + in_enum = False + + if in_enum: + if not line or line.startswith('/*'): + continue + m_enum = RE_ENUM.match(line) + if m_enum.group(3): + cur_id = int(m_enum.group(3)) + vals[m_enum.group(1)] = cur_id + cur_id += 1 + else: + m_def = RE_DEF.match(line) + if m_def: + vals[m_def.group(1)] = tools.to_bytes(m_def.group(2)) + + return vals + + +def run_expo(args): + """Run the expo program""" + ids = calc_ids(args.enum_fname) + + indata = tools.read_file(args.layout) + + outf = io.BytesIO() + + for name, val in ids.items(): + if isinstance(val, int): + outval = b'%d' % val + else: + outval = b'"%s"' % val + find_str = r'\b%s\b' % name + indata = re.sub(tools.to_bytes(find_str), outval, indata) + + outf.write(indata) + data = outf.getvalue() + + with open('/tmp/asc', 'wb') as outf: + outf.write(data) + proc = subprocess.run('dtc', input=data, capture_output=True, check=True) + edtb = proc.stdout + if proc.stderr: + print(proc.stderr) + return 1 + tools.write_file(args.outfile, edtb) + return 0 + + +def parse_args(argv): + """Parse the command-line arguments + + Args: + argv (list of str): List of string arguments + + Returns: + tuple: (options, args) with the command-line options and arugments. + options provides access to the options (e.g. option.debug) + args is a list of string arguments + """ + parser = argparse.ArgumentParser() + parser.add_argument('-e', '--enum-fname', type=str, + help='C file containing enum declaration for expo items') + parser.add_argument('-l', '--layout', type=str, + help='Devicetree file source .dts for expo layout') + parser.add_argument('-o', '--outfile', type=str, + help='Filename to write expo layout dtb') + + return parser.parse_args(argv) + +def start_expo(): + """Start the expo program""" + args = parse_args(sys.argv[1:]) + + ret_code = run_expo(args) + sys.exit(ret_code) + + +if __name__ == "__main__": + start_expo() From patchwork Thu Jun 1 16:23:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1789269 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=bKIm9Rvt; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QXBZG2438z20QB for ; Fri, 2 Jun 2023 02:35:18 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 5236386321; Thu, 1 Jun 2023 18:35:15 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="bKIm9Rvt"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 440B7865D5; Thu, 1 Jun 2023 18:25:58 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mail-il1-x136.google.com (mail-il1-x136.google.com [IPv6:2607:f8b0:4864:20::136]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 574CE865AE for ; Thu, 1 Jun 2023 18:25:37 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x136.google.com with SMTP id e9e14a558f8ab-33b5dba8c6cso3417945ab.2 for ; Thu, 01 Jun 2023 09:25:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1685636703; x=1688228703; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=3qm5lWw0c9ySAtaQPnvISWyE7nNovqY59XuTHWYLyqU=; b=bKIm9Rvt9TkoTOuzWb9V6ChUfuQGp78DudyccEBdKORax8x3OaCzs8JePHAM269u25 1RvWi1HibvTIzQynCfy2B0CViARGfUeNkB6zIiGu1UltVMpsyreg2vOp/Q54zY6LWVI0 CCG9w5RXzfbMJq6lNM37Xgb8brRt4Z7u8zMVg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685636703; x=1688228703; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=3qm5lWw0c9ySAtaQPnvISWyE7nNovqY59XuTHWYLyqU=; b=Jer1Aaviqj1R97+HANLglrDFVmRgq2ppm0ptSA4tBq03ktu2l6BMJ9JgnNe9AB61U1 9D6VTrG7wENYwQLNPcXHLPFOBFoljYQhvv35EGm1rYayN4F/xIwL9LKbCl+ZU5Fm7MIj aOiT+Sae0AIESsWFKo89nu90+rp22SvbijAgVfVjsC6wA6Os3pO2potskDfd0hQTkgBu /dH8IhAJbFoDVmkE1HzpfhnzOTH+TKj0JTmKe1qKyWhiEAwiR2zVqzI8BUGUVMv3ueyY 8stL8oK/QP6781jIprTzu/QcNbkQEwB4w6O4OdU40vk5BId9O+uIb8kZ3yBlcqwT6vPw V45A== X-Gm-Message-State: AC+VfDyOietJcpXpphneDNji8bKtordIDKNvegdL8Mb06GtBvGtgT6FN /WErMTZeffDs60Qc3vG2vZh9PWn8OcC+9v9mOVY= X-Google-Smtp-Source: ACHHUZ7SLmvIlTwnMR5pkwRQgJzktPH3dDJhtPwHqDVPy4FVybhV37P4TCalHQ9/RAj/pv/xI3lKzw== X-Received: by 2002:a92:d581:0:b0:33b:568a:2981 with SMTP id a1-20020a92d581000000b0033b568a2981mr4928732iln.8.1685636701837; Thu, 01 Jun 2023 09:25:01 -0700 (PDT) Received: from sjg1.lan (c-73-14-173-85.hsd1.co.comcast.net. [73.14.173.85]) by smtp.gmail.com with ESMTPSA id l1-20020a922901000000b0033a6e7ee4e3sm3862098ilg.1.2023.06.01.09.25.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 09:25:01 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Heinrich Schuchardt , Tom Rini , Simon Glass , Anatolij Gustschin Subject: [PATCH 40/40] RFC: video: Update stb_truetype Date: Thu, 1 Jun 2023 10:23:04 -0600 Message-ID: <20230601162404.220488-39-sjg@chromium.org> X-Mailer: git-send-email 2.41.0.rc0.172.g3f132b7071-goog In-Reply-To: <20230601162404.220488-1-sjg@chromium.org> References: <20230601162404.220488-1-sjg@chromium.org> MIME-Version: 1.0 X-Mailman-Approved-At: Thu, 01 Jun 2023 18:35:13 +0200 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean This was brought in in 2016 and a number of changes have been made since then. There does not seem to be much change in functionality, but it is a good idea to update from time to time. Bring in the latest version: 5736b15 ("re-add perlin noise again") Add a few necessary functions, with dummies in some cases. Update the tests as there are subtle changes in rendering, perhaps not for the better. Signed-off-by: Simon Glass --- drivers/video/console_truetype.c | 33 + drivers/video/stb_truetype.h | 2257 +++++++++++++++++++++++++++--- test/dm/video.c | 6 +- 3 files changed, 2077 insertions(+), 219 deletions(-) diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c index 288123a2e065..0f9bb49e44f7 100644 --- a/drivers/video/console_truetype.c +++ b/drivers/video/console_truetype.c @@ -62,10 +62,43 @@ static double tt_sqrt(double value) return lo; } +static double tt_fmod(double x, double y) +{ + double rem; + + if (y == 0.0) + return 0.0; + rem = x - (x / y) * y; + + return rem; +} + +/* dummy implementation */ +static double tt_pow(double x, double y) +{ + return 0; +} + +/* dummy implementation */ +static double tt_cos(double val) +{ + return 0; +} + +/* dummy implementation */ +static double tt_acos(double val) +{ + return 0; +} + #define STBTT_ifloor tt_floor #define STBTT_iceil tt_ceil #define STBTT_fabs tt_fabs #define STBTT_sqrt tt_sqrt +#define STBTT_pow tt_pow +#define STBTT_fmod tt_fmod +#define STBTT_cos tt_cos +#define STBTT_acos tt_acos #define STBTT_malloc(size, u) ((void)(u), malloc(size)) #define STBTT_free(size, u) ((void)(u), free(size)) #define STBTT_assert(x) diff --git a/drivers/video/stb_truetype.h b/drivers/video/stb_truetype.h index 438bfce468c7..c6973bb353c3 100644 --- a/drivers/video/stb_truetype.h +++ b/drivers/video/stb_truetype.h @@ -1,11 +1,21 @@ -// stb_truetype.h - v1.08 - public domain -// authored from 2009-2015 by Sean Barrett / RAD Game Tools +// stb_truetype.h - v1.26 - public domain +// authored from 2009-2021 by Sean Barrett / RAD Game Tools +// +// ======================================================================= +// +// NO SECURITY GUARANTEE -- DO NOT USE THIS ON UNTRUSTED FONT FILES +// +// This library does no range checking of the offsets found in the file, +// meaning an attacker can use it to read arbitrary memory. +// +// ======================================================================= // // This library processes TrueType files: // parse files // extract glyph metrics // extract glyph shapes // render glyphs to one-channel bitmaps with antialiasing (box filter) +// render glyphs to one-channel SDF bitmaps (signed-distance field/function) // // Todo: // non-MS cmaps @@ -20,58 +30,68 @@ // // Mikko Mononen: compound shape support, more cmap formats // Tor Andersson: kerning, subpixel rendering -// -// Bug/warning reports/fixes: -// "Zer" on mollyrocket (with fix) -// Cass Everitt -// stoiko (Haemimont Games) -// Brian Hook -// Walter van Niftrik -// David Gow -// David Given -// Ivan-Assen Ivanov -// Anthony Pesch -// Johan Duparc -// Hou Qiming -// Fabian "ryg" Giesen -// Martins Mozeiko -// Cap Petschulat -// Omar Cornut -// github:aloucks -// Peter LaValle -// Sergey Popov -// Giumo X. Clanjor -// Higor Euripedes +// Dougall Johnson: OpenType / Type 2 font handling +// Daniel Ribeiro Maciel: basic GPOS-based kerning // // Misc other: // Ryan Gordon +// Simon Glass +// github:IntellectualKitty +// Imanol Celaya +// Daniel Ribeiro Maciel +// +// Bug/warning reports/fixes: +// "Zer" on mollyrocket Fabian "ryg" Giesen github:NiLuJe +// Cass Everitt Martins Mozeiko github:aloucks +// stoiko (Haemimont Games) Cap Petschulat github:oyvindjam +// Brian Hook Omar Cornut github:vassvik +// Walter van Niftrik Ryan Griege +// David Gow Peter LaValle +// David Given Sergey Popov +// Ivan-Assen Ivanov Giumo X. Clanjor +// Anthony Pesch Higor Euripedes +// Johan Duparc Thomas Fields +// Hou Qiming Derek Vinyard +// Rob Loach Cort Stratton +// Kenney Phillis Jr. Brian Costabile +// Ken Voskuil (kaesve) // // VERSION HISTORY // +// 1.26 (2021-08-28) fix broken rasterizer +// 1.25 (2021-07-11) many fixes +// 1.24 (2020-02-05) fix warning +// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) +// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined +// 1.21 (2019-02-25) fix warning +// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() +// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod +// 1.18 (2018-01-29) add missing function +// 1.17 (2017-07-23) make more arguments const; doc fix +// 1.16 (2017-07-12) SDF support +// 1.15 (2017-03-03) make more arguments const +// 1.14 (2017-01-16) num-fonts-in-TTC function +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts +// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual +// 1.11 (2016-04-02) fix unused-variable warning +// 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef +// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly // 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; // variant PackFontRanges to pack and render in separate phases; // fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); // fixed an assert() bug in the new rasterizer // replace assert() with STBTT_assert() in new rasterizer -// 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine) -// also more precise AA rasterizer, except if shapes overlap -// remove need for STBTT_sort -// 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC -// 1.04 (2015-04-15) typo in example -// 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes // // Full history can be found at the end of this file. // // LICENSE // -// This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevocable license to copy, -// distribute, and modify this file as you see fit. +// See end of file for license information. // // USAGE // -// Include this file in whatever places neeed to refer to it. In ONE C/C++ +// Include this file in whatever places need to refer to it. In ONE C/C++ // file, write: // #define STB_TRUETYPE_IMPLEMENTATION // before the #include of this file. This expands out the actual @@ -87,14 +107,15 @@ // Improved 3D API (more shippable): // #include "stb_rect_pack.h" -- optional, but you really want it // stbtt_PackBegin() -// stbtt_PackSetOversample() -- for improved quality on small fonts +// stbtt_PackSetOversampling() -- for improved quality on small fonts // stbtt_PackFontRanges() -- pack and renders // stbtt_PackEnd() // stbtt_GetPackedQuad() // // "Load" a font file from a memory buffer (you have to keep the buffer loaded) // stbtt_InitFont() -// stbtt_GetFontOffsetForIndex() -- use for TTC font collections +// stbtt_GetFontOffsetForIndex() -- indexing for TTC font collections +// stbtt_GetNumberOfFonts() -- number of fonts for TTC font collections // // Render a unicode codepoint to a bitmap // stbtt_GetCodepointBitmap() -- allocates and returns a bitmap @@ -104,6 +125,7 @@ // Character advance/positioning // stbtt_GetCodepointHMetrics() // stbtt_GetFontVMetrics() +// stbtt_GetFontVMetricsOS2() // stbtt_GetCodepointKernAdvance() // // Starting with version 1.06, the rasterizer was replaced with a new, @@ -159,7 +181,7 @@ // measurement for describing font size, defined as 72 points per inch. // stb_truetype provides a point API for compatibility. However, true // "per inch" conventions don't make much sense on computer displays -// since they different monitors have different number of pixels per +// since different monitors have different number of pixels per // inch. For example, Windows traditionally uses a convention that // there are 96 pixels per inch, thus making 'inch' measurements have // nothing to do with inches, and thus effectively defining a point to @@ -169,6 +191,39 @@ // for non-commercial fonts, thus making fonts scaled in points // according to the TrueType spec incoherently sized in practice. // +// DETAILED USAGE: +// +// Scale: +// Select how high you want the font to be, in points or pixels. +// Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute +// a scale factor SF that will be used by all other functions. +// +// Baseline: +// You need to select a y-coordinate that is the baseline of where +// your text will appear. Call GetFontBoundingBox to get the baseline-relative +// bounding box for all characters. SF*-y0 will be the distance in pixels +// that the worst-case character could extend above the baseline, so if +// you want the top edge of characters to appear at the top of the +// screen where y=0, then you would set the baseline to SF*-y0. +// +// Current point: +// Set the current point where the first character will appear. The +// first character could extend left of the current point; this is font +// dependent. You can either choose a current point that is the leftmost +// point and hope, or add some padding, or check the bounding box or +// left-side-bearing of the first character to be displayed and set +// the current point based on that. +// +// Displaying a character: +// Compute the bounding box of the character. It will contain signed values +// relative to . I.e. if it returns x0,y0,x1,y1, +// then the character should be displayed in the rectangle from +// to = 32 && *text < 128) { stbtt_aligned_quad q; stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9 - glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0); - glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0); - glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1); - glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1); + glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y0); + glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y0); + glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y1); + glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y1); } ++text; } @@ -305,7 +349,7 @@ int main(int argc, char **argv) } return 0; } -#endif +#endif // // Output: // @@ -319,9 +363,9 @@ int main(int argc, char **argv) // :@@. M@M // @@@o@@@@ // :M@@V:@@. -// +// ////////////////////////////////////////////////////////////////////////////// -// +// // Complete program: print "Hello World!" banner, with bugs // #if 0 @@ -375,7 +419,8 @@ int main(int arg, char **argv) //// INTEGRATION WITH YOUR CODEBASE //// //// The following sections allow you to supply alternate definitions -//// of C library functions used by stb_truetype. +//// of C library functions used by stb_truetype, e.g. if you don't +//// link with the C runtime library. #ifdef STB_TRUETYPE_IMPLEMENTATION // #define your own (u)stbtt_int8/16/32 before including to override this @@ -391,7 +436,7 @@ int main(int arg, char **argv) typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1]; typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1]; - // #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h + // e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h #ifndef STBTT_ifloor #include #define STBTT_ifloor(x) ((int) floor(x)) @@ -401,6 +446,18 @@ int main(int arg, char **argv) #ifndef STBTT_sqrt #include #define STBTT_sqrt(x) sqrt(x) + #define STBTT_pow(x,y) pow(x,y) + #endif + + #ifndef STBTT_fmod + #include + #define STBTT_fmod(x,y) fmod(x,y) + #endif + + #ifndef STBTT_cos + #include + #define STBTT_cos(x) cos(x) + #define STBTT_acos(x) acos(x) #endif #ifndef STBTT_fabs @@ -452,6 +509,14 @@ int main(int arg, char **argv) extern "C" { #endif +// private structure +typedef struct +{ + unsigned char *data; + int cursor; + int size; +} stbtt__buf; + ////////////////////////////////////////////////////////////////////////////// // // TEXTURE BAKING API @@ -481,7 +546,7 @@ typedef struct float x1,y1,s1,t1; // bottom-right } stbtt_aligned_quad; -STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, // same data as above +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, // same data as above int char_index, // character to display float *xpos, float *ypos, // pointers to current position in screen pixel space stbtt_aligned_quad *q, // output: quad to draw @@ -496,6 +561,9 @@ STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, // // // It's inefficient; you might want to c&p it and optimize it. +STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap); +// Query the font vertical metrics without having to create a font first. + ////////////////////////////////////////////////////////////////////////////// // @@ -520,7 +588,7 @@ typedef struct stbrp_rect stbrp_rect; STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context); // Initializes a packing context stored in the passed-in stbtt_pack_context. // Future calls using this context will pack characters into the bitmap passed -// in here: a 1-channel bitmap that is weight x height. stride_in_bytes is +// in here: a 1-channel bitmap that is width * height. stride_in_bytes is // the distance from one row to the next (or 0 to mean they are packed tightly // together). "padding" is the amount of padding to leave between each // character (normally you want '1' for bitmaps you'll use as textures with @@ -533,7 +601,7 @@ STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc); #define STBTT_POINT_SIZE(x) (-(x)) -STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size, +STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range); // Creates character bitmaps from the font_index'th font found in fontdata (use // font_index=0 if you don't know what that is). It creates num_chars_in_range @@ -558,7 +626,7 @@ typedef struct unsigned char h_oversample, v_oversample; // don't set these, they're used internally } stbtt_pack_range; -STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); // Creates character bitmaps from multiple ranges of characters stored in // ranges. This will usually create a better-packed bitmap than multiple // calls to stbtt_PackFontRange. Note that you can call this multiple @@ -580,19 +648,25 @@ STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h // To use with PackFontRangesGather etc., you must set it before calls // call to PackFontRangesGatherRects. -STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, // same data as above +STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip); +// If skip != 0, this tells stb_truetype to skip any codepoints for which +// there is no corresponding glyph. If skip=0, which is the default, then +// codepoints without a glyph recived the font's "missing character" glyph, +// typically an empty box by convention. + +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above int char_index, // character to display float *xpos, float *ypos, // pointers to current position in screen pixel space stbtt_aligned_quad *q, // output: quad to draw int align_to_integer); -STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); +STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects); -STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); +STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); // Calling these functions in sequence is roughly equivalent to calling // stbtt_PackFontRanges(). If you more control over the packing of multiple // fonts, or if you want to pack custom data into a font texture, take a look -// at the source to of stbtt_PackFontRanges() and create a custom version +// at the source to of stbtt_PackFontRanges() and create a custom version // using these functions, e.g. call GatherRects multiple times, // building up a single array of rects, then call PackRects once, // then call RenderIntoRects repeatedly. This may result in a @@ -608,6 +682,7 @@ struct stbtt_pack_context { int height; int stride_in_bytes; int padding; + int skip_missing; unsigned int h_oversample, v_oversample; unsigned char *pixels; void *nodes; @@ -619,18 +694,23 @@ struct stbtt_pack_context { // // +STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data); +// This function will determine the number of fonts in a font file. TrueType +// collection (.ttc) files may contain multiple fonts, while TrueType font +// (.ttf) files only contain one font. The number of fonts can be used for +// indexing with the previous function where the index is between zero and one +// less than the total fonts. If an error occurs, -1 is returned. + STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); // Each .ttf/.ttc file may have more than one font. Each font has a sequential // index number starting from 0. Call this function to get the font offset for // a given index; it returns -1 if the index is out of range. A regular .ttf // file will only define one font and it always be at offset 0, so it will -// return '0' for index 0, and -1 for all other indices. You can just skip -// this step if you know it's that kind of font. - +// return '0' for index 0, and -1 for all other indices. -// The following structure is defined publically so you can declare one on +// The following structure is defined publicly so you can declare one on // the stack or as a global or etc, but you should treat it as opaque. -typedef struct stbtt_fontinfo +struct stbtt_fontinfo { void * userdata; unsigned char * data; // pointer to .ttf file @@ -638,10 +718,17 @@ typedef struct stbtt_fontinfo int numGlyphs; // number of glyphs, needed for range checking - int loca,head,glyf,hhea,hmtx,kern; // table locations as offset from start of .ttf + int loca,head,glyf,hhea,hmtx,kern,gpos,svg; // table locations as offset from start of .ttf int index_map; // a cmap mapping for our chosen character encoding int indexToLocFormat; // format needed to map from glyph index to glyph -} stbtt_fontinfo; + + stbtt__buf cff; // cff font data + stbtt__buf charstrings; // the charstring index + stbtt__buf gsubrs; // global charstring subroutines index + stbtt__buf subrs; // private charstring subroutines index + stbtt__buf fontdicts; // array of font dicts + stbtt__buf fdselect; // map from glyph to fontdict +}; STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); // Given an offset into the file that defines a font, this function builds @@ -660,6 +747,7 @@ STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codep // and you want a speed-up, call this function with the character you're // going to process, then use glyph-based functions instead of the // codepoint-based functions. +// Returns 0 if the character codepoint is not defined in the font. ////////////////////////////////////////////////////////////////////////////// @@ -688,6 +776,12 @@ STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, in // these are expressed in unscaled coordinates, so you must multiply by // the scale factor for a given size +STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap); +// analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2 +// table (specific to MS/Windows TTF files). +// +// Returns 1 on success (table present), 0 on failure. + STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1); // the bounding box around all possible characters @@ -707,6 +801,18 @@ STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); // as above, but takes one or more glyph indices for greater efficiency +typedef struct stbtt_kerningentry +{ + int glyph1; // use stbtt_FindGlyphIndex + int glyph2; + int advance; +} stbtt_kerningentry; + +STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info); +STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length); +// Retrieves a complete list of all of the kerning pairs provided by the font +// stbtt_GetKerningTable never writes more than table_length entries and returns how many entries it did write. +// The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1) ////////////////////////////////////////////////////////////////////////////// // @@ -718,7 +824,8 @@ STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, in enum { STBTT_vmove=1, STBTT_vline, - STBTT_vcurve + STBTT_vcurve, + STBTT_vcubic }; #endif @@ -727,7 +834,7 @@ STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, in #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file typedef struct { - stbtt_vertex_type x,y,cx,cy; + stbtt_vertex_type x,y,cx,cy,cx1,cy1; unsigned char type,padding; } stbtt_vertex; #endif @@ -740,7 +847,7 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s // returns # of vertices and fills *vertices with the pointer to them // these are expressed in "unscaled" coordinates // -// The shape is a series of countours. Each one starts with +// The shape is a series of contours. Each one starts with // a STBTT_moveto, then consists of a series of mixed // STBTT_lineto and STBTT_curveto segments. A lineto // draws a line from previous endpoint to its x,y; a curveto @@ -750,6 +857,12 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); // frees the data allocated above +STBTT_DEF unsigned char *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl); +STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg); +STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg); +// fills svg with the character's SVG data. +// returns data size or 0 if SVG not found. + ////////////////////////////////////////////////////////////////////////////// // // BITMAP RENDERING @@ -781,6 +894,10 @@ STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, uns // same as stbtt_MakeCodepointBitmap, but you can specify a subpixel // shift for the character +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint); +// same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering +// is performed (see stbtt_PackSetOversampling) + STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); // get the bbox of the bitmap centered around the glyph origin; so the // bitmap width is ix1-ix0, height is iy1-iy0, and location to place @@ -798,6 +915,7 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff); STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph); STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph); +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph); STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); @@ -820,6 +938,64 @@ STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap int invert, // if non-zero, vertically flip shape void *userdata); // context for to STBTT_MALLOC +////////////////////////////////////////////////////////////////////////////// +// +// Signed Distance Function (or Field) rendering + +STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata); +// frees the SDF bitmap allocated below + +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +// These functions compute a discretized SDF field for a single character, suitable for storing +// in a single-channel texture, sampling with bilinear filtering, and testing against +// larger than some threshold to produce scalable fonts. +// info -- the font +// scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap +// glyph/codepoint -- the character to generate the SDF for +// padding -- extra "pixels" around the character which are filled with the distance to the character (not 0), +// which allows effects like bit outlines +// onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character) +// pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale) +// if positive, > onedge_value is inside; if negative, < onedge_value is inside +// width,height -- output height & width of the SDF bitmap (including padding) +// xoff,yoff -- output origin of the character +// return value -- a 2D array of bytes 0..255, width*height in size +// +// pixel_dist_scale & onedge_value are a scale & bias that allows you to make +// optimal use of the limited 0..255 for your application, trading off precision +// and special effects. SDF values outside the range 0..255 are clamped to 0..255. +// +// Example: +// scale = stbtt_ScaleForPixelHeight(22) +// padding = 5 +// onedge_value = 180 +// pixel_dist_scale = 180/5.0 = 36.0 +// +// This will create an SDF bitmap in which the character is about 22 pixels +// high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled +// shape, sample the SDF at each pixel and fill the pixel if the SDF value +// is greater than or equal to 180/255. (You'll actually want to antialias, +// which is beyond the scope of this example.) Additionally, you can compute +// offset outlines (e.g. to stroke the character border inside & outside, +// or only outside). For example, to fill outside the character up to 3 SDF +// pixels, you would compare against (180-36.0*3)/255 = 72/255. The above +// choice of variables maps a range from 5 pixels outside the shape to +// 2 pixels inside the shape to 0..255; this is intended primarily for apply +// outside effects only (the interior range is needed to allow proper +// antialiasing of the font at *smaller* sizes) +// +// The function computes the SDF analytically at each SDF pixel, not by e.g. +// building a higher-res bitmap and approximating it. In theory the quality +// should be as high as possible for an SDF of this size & representation, but +// unclear if this is true in practice (perhaps building a higher-res bitmap +// and computing from that can allow drop-out prevention). +// +// The algorithm has not been optimized at all, so expect it to be slow +// if computing lots of characters or very large sizes. + + + ////////////////////////////////////////////////////////////////////////////// // // Finding the right font... @@ -943,6 +1119,158 @@ typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERS #define STBTT_RASTERIZER_VERSION 2 #endif +#ifdef _MSC_VER +#define STBTT__NOTUSED(v) (void)(v) +#else +#define STBTT__NOTUSED(v) (void)sizeof(v) +#endif + +////////////////////////////////////////////////////////////////////////// +// +// stbtt__buf helpers to parse data from file +// + +static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b) +{ + if (b->cursor >= b->size) + return 0; + return b->data[b->cursor++]; +} + +static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b) +{ + if (b->cursor >= b->size) + return 0; + return b->data[b->cursor]; +} + +static void stbtt__buf_seek(stbtt__buf *b, int o) +{ + STBTT_assert(!(o > b->size || o < 0)); + b->cursor = (o > b->size || o < 0) ? b->size : o; +} + +static void stbtt__buf_skip(stbtt__buf *b, int o) +{ + stbtt__buf_seek(b, b->cursor + o); +} + +static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n) +{ + stbtt_uint32 v = 0; + int i; + STBTT_assert(n >= 1 && n <= 4); + for (i = 0; i < n; i++) + v = (v << 8) | stbtt__buf_get8(b); + return v; +} + +static stbtt__buf stbtt__new_buf(const void *p, size_t size) +{ + stbtt__buf r; + STBTT_assert(size < 0x40000000); + r.data = (stbtt_uint8*) p; + r.size = (int) size; + r.cursor = 0; + return r; +} + +#define stbtt__buf_get16(b) stbtt__buf_get((b), 2) +#define stbtt__buf_get32(b) stbtt__buf_get((b), 4) + +static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s) +{ + stbtt__buf r = stbtt__new_buf(NULL, 0); + if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r; + r.data = b->data + o; + r.size = s; + return r; +} + +static stbtt__buf stbtt__cff_get_index(stbtt__buf *b) +{ + int count, start, offsize; + start = b->cursor; + count = stbtt__buf_get16(b); + if (count) { + offsize = stbtt__buf_get8(b); + STBTT_assert(offsize >= 1 && offsize <= 4); + stbtt__buf_skip(b, offsize * count); + stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1); + } + return stbtt__buf_range(b, start, b->cursor - start); +} + +static stbtt_uint32 stbtt__cff_int(stbtt__buf *b) +{ + int b0 = stbtt__buf_get8(b); + if (b0 >= 32 && b0 <= 246) return b0 - 139; + else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108; + else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108; + else if (b0 == 28) return stbtt__buf_get16(b); + else if (b0 == 29) return stbtt__buf_get32(b); + STBTT_assert(0); + return 0; +} + +static void stbtt__cff_skip_operand(stbtt__buf *b) { + int v, b0 = stbtt__buf_peek8(b); + STBTT_assert(b0 >= 28); + if (b0 == 30) { + stbtt__buf_skip(b, 1); + while (b->cursor < b->size) { + v = stbtt__buf_get8(b); + if ((v & 0xF) == 0xF || (v >> 4) == 0xF) + break; + } + } else { + stbtt__cff_int(b); + } +} + +static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key) +{ + stbtt__buf_seek(b, 0); + while (b->cursor < b->size) { + int start = b->cursor, end, op; + while (stbtt__buf_peek8(b) >= 28) + stbtt__cff_skip_operand(b); + end = b->cursor; + op = stbtt__buf_get8(b); + if (op == 12) op = stbtt__buf_get8(b) | 0x100; + if (op == key) return stbtt__buf_range(b, start, end-start); + } + return stbtt__buf_range(b, 0, 0); +} + +static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out) +{ + int i; + stbtt__buf operands = stbtt__dict_get(b, key); + for (i = 0; i < outcount && operands.cursor < operands.size; i++) + out[i] = stbtt__cff_int(&operands); +} + +static int stbtt__cff_index_count(stbtt__buf *b) +{ + stbtt__buf_seek(b, 0); + return stbtt__buf_get16(b); +} + +static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i) +{ + int count, offsize, start, end; + stbtt__buf_seek(&b, 0); + count = stbtt__buf_get16(&b); + offsize = stbtt__buf_get8(&b); + STBTT_assert(i >= 0 && i < count); + STBTT_assert(offsize >= 1 && offsize <= 4); + stbtt__buf_skip(&b, i*offsize); + start = stbtt__buf_get(&b, offsize); + end = stbtt__buf_get(&b, offsize); + return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start); +} + ////////////////////////////////////////////////////////////////////////// // // accessors to parse data from file @@ -955,32 +1283,22 @@ typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERS #define ttCHAR(p) (* (stbtt_int8 *) (p)) #define ttFixed(p) ttLONG(p) -#if defined(STB_TRUETYPE_BIGENDIAN) && !defined(ALLOW_UNALIGNED_TRUETYPE) - - #define ttUSHORT(p) (* (stbtt_uint16 *) (p)) - #define ttSHORT(p) (* (stbtt_int16 *) (p)) - #define ttULONG(p) (* (stbtt_uint32 *) (p)) - #define ttLONG(p) (* (stbtt_int32 *) (p)) - -#else - - static stbtt_uint16 ttUSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; } - static stbtt_int16 ttSHORT(const stbtt_uint8 *p) { return p[0]*256 + p[1]; } - static stbtt_uint32 ttULONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } - static stbtt_int32 ttLONG(const stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } - -#endif +static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } +static stbtt_int16 ttSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } +static stbtt_uint32 ttULONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } +static stbtt_int32 ttLONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } #define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) #define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3]) -static int stbtt__isfont(const stbtt_uint8 *font) +static int stbtt__isfont(stbtt_uint8 *font) { // check the version number if (stbtt_tag4(font, '1',0,0,0)) return 1; // TrueType 1 if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this! if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0 + if (stbtt_tag(font, "true")) return 1; // Apple specification for TrueType fonts return 0; } @@ -998,7 +1316,7 @@ static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, return 0; } -STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *font_collection, int index) +static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index) { // if it's just a font, there's only one valid index if (stbtt__isfont(font_collection)) @@ -1017,14 +1335,59 @@ STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *font_collection, return -1; } -STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data2, int fontstart) +static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection) +{ + // if it's just a font, there's only one valid font + if (stbtt__isfont(font_collection)) + return 1; + + // check if it's a TTC + if (stbtt_tag(font_collection, "ttcf")) { + // version 1? + if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { + return ttLONG(font_collection+8); + } + } + return 0; +} + +static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict) +{ + stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 }; + stbtt__buf pdict; + stbtt__dict_get_ints(&fontdict, 18, 2, private_loc); + if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0); + pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]); + stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff); + if (!subrsoff) return stbtt__new_buf(NULL, 0); + stbtt__buf_seek(&cff, private_loc[1]+subrsoff); + return stbtt__cff_get_index(&cff); +} + +// since most people won't use this, find this table the first time it's needed +static int stbtt__get_svg(stbtt_fontinfo *info) +{ + stbtt_uint32 t; + if (info->svg < 0) { + t = stbtt__find_table(info->data, info->fontstart, "SVG "); + if (t) { + stbtt_uint32 offset = ttULONG(info->data + t + 2); + info->svg = t + offset; + } else { + info->svg = 0; + } + } + return info->svg; +} + +static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart) { - stbtt_uint8 *data = (stbtt_uint8 *) data2; stbtt_uint32 cmap, t; stbtt_int32 i,numTables; info->data = data; info->fontstart = fontstart; + info->cff = stbtt__new_buf(NULL, 0); cmap = stbtt__find_table(data, fontstart, "cmap"); // required info->loca = stbtt__find_table(data, fontstart, "loca"); // required @@ -1033,8 +1396,62 @@ STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data2, i info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required info->kern = stbtt__find_table(data, fontstart, "kern"); // not required - if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx) + info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required + + if (!cmap || !info->head || !info->hhea || !info->hmtx) return 0; + if (info->glyf) { + // required for truetype + if (!info->loca) return 0; + } else { + // initialization for CFF / Type2 fonts (OTF) + stbtt__buf b, topdict, topdictidx; + stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0; + stbtt_uint32 cff; + + cff = stbtt__find_table(data, fontstart, "CFF "); + if (!cff) return 0; + + info->fontdicts = stbtt__new_buf(NULL, 0); + info->fdselect = stbtt__new_buf(NULL, 0); + + // @TODO this should use size from table (not 512MB) + info->cff = stbtt__new_buf(data+cff, 512*1024*1024); + b = info->cff; + + // read the header + stbtt__buf_skip(&b, 2); + stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize + + // @TODO the name INDEX could list multiple fonts, + // but we just use the first one. + stbtt__cff_get_index(&b); // name INDEX + topdictidx = stbtt__cff_get_index(&b); + topdict = stbtt__cff_index_get(topdictidx, 0); + stbtt__cff_get_index(&b); // string INDEX + info->gsubrs = stbtt__cff_get_index(&b); + + stbtt__dict_get_ints(&topdict, 17, 1, &charstrings); + stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype); + stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff); + stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff); + info->subrs = stbtt__get_subrs(b, topdict); + + // we only support Type 2 charstrings + if (cstype != 2) return 0; + if (charstrings == 0) return 0; + + if (fdarrayoff) { + // looks like a CID font + if (!fdselectoff) return 0; + stbtt__buf_seek(&b, fdarrayoff); + info->fontdicts = stbtt__cff_get_index(&b); + info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff); + } + + stbtt__buf_seek(&b, charstrings); + info->charstrings = stbtt__cff_get_index(&b); + } t = stbtt__find_table(data, fontstart, "maxp"); if (t) @@ -1042,6 +1459,8 @@ STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data2, i else info->numGlyphs = 0xffff; + info->svg = -1; + // find a cmap encoding table we understand *now* to avoid searching // later. (todo: could make this installable) // the same regardless of glyph. @@ -1125,12 +1544,12 @@ STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codep search += 2; { - stbtt_uint16 offset, start; + stbtt_uint16 offset, start, last; stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1); - STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item)); start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); - if (unicode_codepoint < start) + last = ttUSHORT(data + endCount + 2*item); + if (unicode_codepoint < start || unicode_codepoint > last) return 0; offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); @@ -1185,6 +1604,8 @@ static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) { int g1,g2; + STBTT_assert(!info->cff.size); + if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format @@ -1199,15 +1620,21 @@ static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) return g1==g2 ? -1 : g1; // if length is 0, return -1 } +static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); + STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) { - int g = stbtt__GetGlyfOffset(info, glyph_index); - if (g < 0) return 0; + if (info->cff.size) { + stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1); + } else { + int g = stbtt__GetGlyfOffset(info, glyph_index); + if (g < 0) return 0; - if (x0) *x0 = ttSHORT(info->data + g + 2); - if (y0) *y0 = ttSHORT(info->data + g + 4); - if (x1) *x1 = ttSHORT(info->data + g + 6); - if (y1) *y1 = ttSHORT(info->data + g + 8); + if (x0) *x0 = ttSHORT(info->data + g + 2); + if (y0) *y0 = ttSHORT(info->data + g + 4); + if (x1) *x1 = ttSHORT(info->data + g + 6); + if (y1) *y1 = ttSHORT(info->data + g + 8); + } return 1; } @@ -1219,7 +1646,10 @@ STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, i STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index) { stbtt_int16 numberOfContours; - int g = stbtt__GetGlyfOffset(info, glyph_index); + int g; + if (info->cff.size) + return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0; + g = stbtt__GetGlyfOffset(info, glyph_index); if (g < 0) return 1; numberOfContours = ttSHORT(info->data + g); return numberOfContours == 0; @@ -1241,7 +1671,7 @@ static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_ return num_vertices; } -STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) { stbtt_int16 numberOfContours; stbtt_uint8 *endPtsOfContours; @@ -1337,7 +1767,7 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s if (i != 0) num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); - // now start the new one + // now start the new one start_off = !(flags & 1); if (start_off) { // if we start off with an off-curve point, then when we need to find a point on the curve @@ -1379,7 +1809,7 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s } } num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); - } else if (numberOfContours == -1) { + } else if (numberOfContours < 0) { // Compound shapes. int more = 1; stbtt_uint8 *comp = data + g + 10; @@ -1390,7 +1820,7 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s int comp_num_verts = 0, i; stbtt_vertex *comp_verts = 0, *tmp = 0; float mtx[6] = {1,0,0,1,0,0}, m, n; - + flags = ttSHORT(comp); comp+=2; gidx = ttSHORT(comp); comp+=2; @@ -1420,7 +1850,7 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s mtx[2] = ttSHORT(comp)/16384.0f; comp+=2; mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; } - + // Find transformation scales. m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]); n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]); @@ -1446,7 +1876,7 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s if (comp_verts) STBTT_free(comp_verts, info->userdata); return 0; } - if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); + if (num_vertices > 0 && vertices) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex)); if (vertices) STBTT_free(vertices, info->userdata); vertices = tmp; @@ -1456,9 +1886,6 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s // More components ? more = flags & (1<<5); } - } else if (numberOfContours < 0) { - // @TODO other compound variations? - STBTT_assert(0); } else { // numberOfCounters == 0, do nothing } @@ -1467,6 +1894,414 @@ STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, s return num_vertices; } +typedef struct +{ + int bounds; + int started; + float first_x, first_y; + float x, y; + stbtt_int32 min_x, max_x, min_y, max_y; + + stbtt_vertex *pvertices; + int num_vertices; +} stbtt__csctx; + +#define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0} + +static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y) +{ + if (x > c->max_x || !c->started) c->max_x = x; + if (y > c->max_y || !c->started) c->max_y = y; + if (x < c->min_x || !c->started) c->min_x = x; + if (y < c->min_y || !c->started) c->min_y = y; + c->started = 1; +} + +static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1) +{ + if (c->bounds) { + stbtt__track_vertex(c, x, y); + if (type == STBTT_vcubic) { + stbtt__track_vertex(c, cx, cy); + stbtt__track_vertex(c, cx1, cy1); + } + } else { + stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy); + c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1; + c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1; + } + c->num_vertices++; +} + +static void stbtt__csctx_close_shape(stbtt__csctx *ctx) +{ + if (ctx->first_x != ctx->x || ctx->first_y != ctx->y) + stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy) +{ + stbtt__csctx_close_shape(ctx); + ctx->first_x = ctx->x = ctx->x + dx; + ctx->first_y = ctx->y = ctx->y + dy; + stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy) +{ + ctx->x += dx; + ctx->y += dy; + stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); +} + +static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3) +{ + float cx1 = ctx->x + dx1; + float cy1 = ctx->y + dy1; + float cx2 = cx1 + dx2; + float cy2 = cy1 + dy2; + ctx->x = cx2 + dx3; + ctx->y = cy2 + dy3; + stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2); +} + +static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n) +{ + int count = stbtt__cff_index_count(&idx); + int bias = 107; + if (count >= 33900) + bias = 32768; + else if (count >= 1240) + bias = 1131; + n += bias; + if (n < 0 || n >= count) + return stbtt__new_buf(NULL, 0); + return stbtt__cff_index_get(idx, n); +} + +static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index) +{ + stbtt__buf fdselect = info->fdselect; + int nranges, start, end, v, fmt, fdselector = -1, i; + + stbtt__buf_seek(&fdselect, 0); + fmt = stbtt__buf_get8(&fdselect); + if (fmt == 0) { + // untested + stbtt__buf_skip(&fdselect, glyph_index); + fdselector = stbtt__buf_get8(&fdselect); + } else if (fmt == 3) { + nranges = stbtt__buf_get16(&fdselect); + start = stbtt__buf_get16(&fdselect); + for (i = 0; i < nranges; i++) { + v = stbtt__buf_get8(&fdselect); + end = stbtt__buf_get16(&fdselect); + if (glyph_index >= start && glyph_index < end) { + fdselector = v; + break; + } + start = end; + } + } + if (fdselector == -1) stbtt__new_buf(NULL, 0); + return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector)); +} + +static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c) +{ + int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0; + int has_subrs = 0, clear_stack; + float s[48]; + stbtt__buf subr_stack[10], subrs = info->subrs, b; + float f; + +#define STBTT__CSERR(s) (0) + + // this currently ignores the initial width value, which isn't needed if we have hmtx + b = stbtt__cff_index_get(info->charstrings, glyph_index); + while (b.cursor < b.size) { + i = 0; + clear_stack = 1; + b0 = stbtt__buf_get8(&b); + switch (b0) { + // @TODO implement hinting + case 0x13: // hintmask + case 0x14: // cntrmask + if (in_header) + maskbits += (sp / 2); // implicit "vstem" + in_header = 0; + stbtt__buf_skip(&b, (maskbits + 7) / 8); + break; + + case 0x01: // hstem + case 0x03: // vstem + case 0x12: // hstemhm + case 0x17: // vstemhm + maskbits += (sp / 2); + break; + + case 0x15: // rmoveto + in_header = 0; + if (sp < 2) return STBTT__CSERR("rmoveto stack"); + stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]); + break; + case 0x04: // vmoveto + in_header = 0; + if (sp < 1) return STBTT__CSERR("vmoveto stack"); + stbtt__csctx_rmove_to(c, 0, s[sp-1]); + break; + case 0x16: // hmoveto + in_header = 0; + if (sp < 1) return STBTT__CSERR("hmoveto stack"); + stbtt__csctx_rmove_to(c, s[sp-1], 0); + break; + + case 0x05: // rlineto + if (sp < 2) return STBTT__CSERR("rlineto stack"); + for (; i + 1 < sp; i += 2) + stbtt__csctx_rline_to(c, s[i], s[i+1]); + break; + + // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical + // starting from a different place. + + case 0x07: // vlineto + if (sp < 1) return STBTT__CSERR("vlineto stack"); + goto vlineto; + case 0x06: // hlineto + if (sp < 1) return STBTT__CSERR("hlineto stack"); + for (;;) { + if (i >= sp) break; + stbtt__csctx_rline_to(c, s[i], 0); + i++; + vlineto: + if (i >= sp) break; + stbtt__csctx_rline_to(c, 0, s[i]); + i++; + } + break; + + case 0x1F: // hvcurveto + if (sp < 4) return STBTT__CSERR("hvcurveto stack"); + goto hvcurveto; + case 0x1E: // vhcurveto + if (sp < 4) return STBTT__CSERR("vhcurveto stack"); + for (;;) { + if (i + 3 >= sp) break; + stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f); + i += 4; + hvcurveto: + if (i + 3 >= sp) break; + stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]); + i += 4; + } + break; + + case 0x08: // rrcurveto + if (sp < 6) return STBTT__CSERR("rcurveline stack"); + for (; i + 5 < sp; i += 6) + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + break; + + case 0x18: // rcurveline + if (sp < 8) return STBTT__CSERR("rcurveline stack"); + for (; i + 5 < sp - 2; i += 6) + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack"); + stbtt__csctx_rline_to(c, s[i], s[i+1]); + break; + + case 0x19: // rlinecurve + if (sp < 8) return STBTT__CSERR("rlinecurve stack"); + for (; i + 1 < sp - 6; i += 2) + stbtt__csctx_rline_to(c, s[i], s[i+1]); + if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack"); + stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); + break; + + case 0x1A: // vvcurveto + case 0x1B: // hhcurveto + if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack"); + f = 0.0; + if (sp & 1) { f = s[i]; i++; } + for (; i + 3 < sp; i += 4) { + if (b0 == 0x1B) + stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0); + else + stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]); + f = 0.0; + } + break; + + case 0x0A: // callsubr + if (!has_subrs) { + if (info->fdselect.size) + subrs = stbtt__cid_get_glyph_subrs(info, glyph_index); + has_subrs = 1; + } + // FALLTHROUGH + case 0x1D: // callgsubr + if (sp < 1) return STBTT__CSERR("call(g|)subr stack"); + v = (int) s[--sp]; + if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit"); + subr_stack[subr_stack_height++] = b; + b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v); + if (b.size == 0) return STBTT__CSERR("subr not found"); + b.cursor = 0; + clear_stack = 0; + break; + + case 0x0B: // return + if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr"); + b = subr_stack[--subr_stack_height]; + clear_stack = 0; + break; + + case 0x0E: // endchar + stbtt__csctx_close_shape(c); + return 1; + + case 0x0C: { // two-byte escape + float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6; + float dx, dy; + int b1 = stbtt__buf_get8(&b); + switch (b1) { + // @TODO These "flex" implementations ignore the flex-depth and resolution, + // and always draw beziers. + case 0x22: // hflex + if (sp < 7) return STBTT__CSERR("hflex stack"); + dx1 = s[0]; + dx2 = s[1]; + dy2 = s[2]; + dx3 = s[3]; + dx4 = s[4]; + dx5 = s[5]; + dx6 = s[6]; + stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0); + stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0); + break; + + case 0x23: // flex + if (sp < 13) return STBTT__CSERR("flex stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dy3 = s[5]; + dx4 = s[6]; + dy4 = s[7]; + dx5 = s[8]; + dy5 = s[9]; + dx6 = s[10]; + dy6 = s[11]; + //fd is s[12] + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); + stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); + break; + + case 0x24: // hflex1 + if (sp < 9) return STBTT__CSERR("hflex1 stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dx4 = s[5]; + dx5 = s[6]; + dy5 = s[7]; + dx6 = s[8]; + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0); + stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5)); + break; + + case 0x25: // flex1 + if (sp < 11) return STBTT__CSERR("flex1 stack"); + dx1 = s[0]; + dy1 = s[1]; + dx2 = s[2]; + dy2 = s[3]; + dx3 = s[4]; + dy3 = s[5]; + dx4 = s[6]; + dy4 = s[7]; + dx5 = s[8]; + dy5 = s[9]; + dx6 = dy6 = s[10]; + dx = dx1+dx2+dx3+dx4+dx5; + dy = dy1+dy2+dy3+dy4+dy5; + if (STBTT_fabs(dx) > STBTT_fabs(dy)) + dy6 = -dy; + else + dx6 = -dx; + stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); + stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); + break; + + default: + return STBTT__CSERR("unimplemented"); + } + } break; + + default: + if (b0 != 255 && b0 != 28 && b0 < 32) + return STBTT__CSERR("reserved operator"); + + // push immediate + if (b0 == 255) { + f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000; + } else { + stbtt__buf_skip(&b, -1); + f = (float)(stbtt_int16)stbtt__cff_int(&b); + } + if (sp >= 48) return STBTT__CSERR("push stack overflow"); + s[sp++] = f; + clear_stack = 0; + break; + } + if (clear_stack) sp = 0; + } + return STBTT__CSERR("no endchar"); + +#undef STBTT__CSERR +} + +static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + // runs the charstring twice, once to count and once to output (to avoid realloc) + stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1); + stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0); + if (stbtt__run_charstring(info, glyph_index, &count_ctx)) { + *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata); + output_ctx.pvertices = *pvertices; + if (stbtt__run_charstring(info, glyph_index, &output_ctx)) { + STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices); + return output_ctx.num_vertices; + } + } + *pvertices = NULL; + return 0; +} + +static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) +{ + stbtt__csctx c = STBTT__CSCTX_INIT(1); + int r = stbtt__run_charstring(info, glyph_index, &c); + if (x0) *x0 = r ? c.min_x : 0; + if (y0) *y0 = r ? c.min_y : 0; + if (x1) *x1 = r ? c.max_x : 0; + if (y1) *y1 = r ? c.max_y : 0; + return r ? c.num_vertices : 0; +} + +STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) +{ + if (!info->cff.size) + return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices); + else + return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices); +} + STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing) { stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34); @@ -1479,7 +2314,49 @@ STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_inde } } -STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info) +{ + stbtt_uint8 *data = info->data + info->kern; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + return ttUSHORT(data+10); +} + +STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length) +{ + stbtt_uint8 *data = info->data + info->kern; + int k, length; + + // we only look at the first table. it must be 'horizontal' and format 0. + if (!info->kern) + return 0; + if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 + return 0; + if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format + return 0; + + length = ttUSHORT(data+10); + if (table_length < length) + length = table_length; + + for (k = 0; k < length; k++) + { + table[k].glyph1 = ttUSHORT(data+18+(k*6)); + table[k].glyph2 = ttUSHORT(data+20+(k*6)); + table[k].advance = ttSHORT(data+22+(k*6)); + } + + return length; +} + +static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) { stbtt_uint8 *data = info->data + info->kern; stbtt_uint32 needle, straw; @@ -1509,9 +2386,242 @@ STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, return 0; } +static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph) +{ + stbtt_uint16 coverageFormat = ttUSHORT(coverageTable); + switch (coverageFormat) { + case 1: { + stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2); + + // Binary search. + stbtt_int32 l=0, r=glyphCount-1, m; + int straw, needle=glyph; + while (l <= r) { + stbtt_uint8 *glyphArray = coverageTable + 4; + stbtt_uint16 glyphID; + m = (l + r) >> 1; + glyphID = ttUSHORT(glyphArray + 2 * m); + straw = glyphID; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + return m; + } + } + break; + } + + case 2: { + stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2); + stbtt_uint8 *rangeArray = coverageTable + 4; + + // Binary search. + stbtt_int32 l=0, r=rangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *rangeRecord; + m = (l + r) >> 1; + rangeRecord = rangeArray + 6 * m; + strawStart = ttUSHORT(rangeRecord); + strawEnd = ttUSHORT(rangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else { + stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4); + return startCoverageIndex + glyph - strawStart; + } + } + break; + } + + default: return -1; // unsupported + } + + return -1; +} + +static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) +{ + stbtt_uint16 classDefFormat = ttUSHORT(classDefTable); + switch (classDefFormat) + { + case 1: { + stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2); + stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4); + stbtt_uint8 *classDef1ValueArray = classDefTable + 6; + + if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount) + return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID)); + break; + } + + case 2: { + stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2); + stbtt_uint8 *classRangeRecords = classDefTable + 4; + + // Binary search. + stbtt_int32 l=0, r=classRangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *classRangeRecord; + m = (l + r) >> 1; + classRangeRecord = classRangeRecords + 6 * m; + strawStart = ttUSHORT(classRangeRecord); + strawEnd = ttUSHORT(classRangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else + return (stbtt_int32)ttUSHORT(classRangeRecord + 4); + } + break; + } + + default: + return -1; // Unsupported definition type, return an error. + } + + // "All glyphs not assigned to a class fall into class 0". (OpenType spec) + return 0; +} + +// Define to STBTT_assert(x) if you want to break on unimplemented formats. +#define STBTT_GPOS_TODO_assert(x) + +static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +{ + stbtt_uint16 lookupListOffset; + stbtt_uint8 *lookupList; + stbtt_uint16 lookupCount; + stbtt_uint8 *data; + stbtt_int32 i, sti; + + if (!info->gpos) return 0; + + data = info->data + info->gpos; + + if (ttUSHORT(data+0) != 1) return 0; // Major version 1 + if (ttUSHORT(data+2) != 0) return 0; // Minor version 0 + + lookupListOffset = ttUSHORT(data+8); + lookupList = data + lookupListOffset; + lookupCount = ttUSHORT(lookupList); + + for (i=0; i= pairSetCount) return 0; + + needle=glyph2; + r=pairValueCount-1; + l=0; + + // Binary search. + while (l <= r) { + stbtt_uint16 secondGlyph; + stbtt_uint8 *pairValue; + m = (l + r) >> 1; + pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m; + secondGlyph = ttUSHORT(pairValue); + straw = secondGlyph; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + stbtt_int16 xAdvance = ttSHORT(pairValue + 2); + return xAdvance; + } + } + } else + return 0; + break; + } + + case 2: { + stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); + stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); + if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats? + stbtt_uint16 classDef1Offset = ttUSHORT(table + 8); + stbtt_uint16 classDef2Offset = ttUSHORT(table + 10); + int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1); + int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2); + + stbtt_uint16 class1Count = ttUSHORT(table + 12); + stbtt_uint16 class2Count = ttUSHORT(table + 14); + stbtt_uint8 *class1Records, *class2Records; + stbtt_int16 xAdvance; + + if (glyph1class < 0 || glyph1class >= class1Count) return 0; // malformed + if (glyph2class < 0 || glyph2class >= class2Count) return 0; // malformed + + class1Records = table + 16; + class2Records = class1Records + 2 * (glyph1class * class2Count); + xAdvance = ttSHORT(class2Records + 2 * glyph2class); + return xAdvance; + } else + return 0; + break; + } + + default: + return 0; // Unsupported position format + } + } + } + + return 0; +} + +STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2) +{ + int xAdvance = 0; + + if (info->gpos) + xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2); + else if (info->kern) + xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2); + + return xAdvance; +} + STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2) { - if (!info->kern) // if no kerning table, don't waste time looking up both codepoint->glyphs + if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs return 0; return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2)); } @@ -1528,6 +2638,17 @@ STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, in if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8); } +STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap) +{ + int tab = stbtt__find_table(info->data, info->fontstart, "OS/2"); + if (!tab) + return 0; + if (typoAscent ) *typoAscent = ttSHORT(info->data+tab + 68); + if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70); + if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72); + return 1; +} + STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1) { *x0 = ttSHORT(info->data + info->head + 36); @@ -1553,6 +2674,45 @@ STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) STBTT_free(v, info->userdata); } +STBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl) +{ + int i; + stbtt_uint8 *data = info->data; + stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *) info); + + int numEntries = ttUSHORT(svg_doc_list); + stbtt_uint8 *svg_docs = svg_doc_list + 2; + + for(i=0; i= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2))) + return svg_doc; + } + return 0; +} + +STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg) +{ + stbtt_uint8 *data = info->data; + stbtt_uint8 *svg_doc; + + if (info->svg == 0) + return 0; + + svg_doc = stbtt_FindSVGDoc(info, gl); + if (svg_doc != NULL) { + *svg = (char *) data + info->svg + ttULONG(svg_doc + 4); + return ttULONG(svg_doc + 8); + } else { + return 0; + } +} + +STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg) +{ + return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg); +} + ////////////////////////////////////////////////////////////////////////////// // // antialiasing software rasterizer @@ -1560,7 +2720,7 @@ STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) { - int x0,y0,x1,y1; + int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) { // e.g. space character if (ix0) *ix0 = 0; @@ -1624,7 +2784,7 @@ static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata) hh->num_remaining_in_head_chunk = count; } --hh->num_remaining_in_head_chunk; - return (char *) (hh->head) + size * hh->num_remaining_in_head_chunk; + return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk; } } @@ -1676,8 +2836,9 @@ static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, i { stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + STBTT_assert(z != NULL); if (!z) return z; - + // round dx down to avoid overshooting if (dxdy < 0) z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy); @@ -1697,6 +2858,7 @@ static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, i { stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + STBTT_assert(z != NULL); //STBTT_assert(e->y0 <= start_point); if (!z) return z; z->fdx = dxdy; @@ -1754,7 +2916,7 @@ static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__ac } } } - + e = e->next; } } @@ -1768,13 +2930,10 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int s; // vertical subsample index unsigned char scanline_data[512], *scanline; - if (result->w > 512) { + if (result->w > 512) scanline = (unsigned char *) STBTT_malloc(result->w, userdata); - if (!scanline) - return; - } else { + else scanline = scanline_data; - } y = off_y * vsubsample; e[n].y0 = (off_y + result->h) * (float) vsubsample + 1; @@ -1824,23 +2983,23 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, while (e->y0 <= scan_y) { if (e->y1 > scan_y) { stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata); - if (!z) - return; - // find insertion point - if (active == NULL) - active = z; - else if (z->x < active->x) { - // insert at front - z->next = active; - active = z; - } else { - // find thing to insert AFTER - stbtt__active_edge *p = active; - while (p->next && p->next->x < z->x) - p = p->next; - // at this point, p->next->x is NOT < z->x - z->next = p->next; - p->next = z; + if (z != NULL) { + // find insertion point + if (active == NULL) + active = z; + else if (z->x < active->x) { + // insert at front + z->next = active; + active = z; + } else { + // find thing to insert AFTER + stbtt__active_edge *p = active; + while (p->next && p->next->x < z->x) + p = p->next; + // at this point, p->next->x is NOT < z->x + z->next = p->next; + p->next = z; + } } } ++e; @@ -1903,6 +3062,23 @@ static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edg } } +static float stbtt__sized_trapezoid_area(float height, float top_width, float bottom_width) +{ + STBTT_assert(top_width >= 0); + STBTT_assert(bottom_width >= 0); + return (top_width + bottom_width) / 2.0f * height; +} + +static float stbtt__position_trapezoid_area(float height, float tx0, float tx1, float bx0, float bx1) +{ + return stbtt__sized_trapezoid_area(height, tx1 - tx0, bx1 - bx0); +} + +static float stbtt__sized_triangle_area(float height, float width) +{ + return height * width / 2; +} + static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top) { float y_bottom = y_top+1; @@ -1957,13 +3133,13 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, float height; // simple case, only spans one pixel int x = (int) x_top; - height = sy1 - sy0; + height = (sy1 - sy0) * e->direction; STBTT_assert(x >= 0 && x < len); - scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height; - scanline_fill[x] += e->direction * height; // everything right of this pixel is filled + scanline[x] += stbtt__position_trapezoid_area(height, x_top, x+1.0f, x_bottom, x+1.0f); + scanline_fill[x] += height; // everything right of this pixel is filled } else { int x,x1,x2; - float y_crossing, step, sign, area; + float y_crossing, y_final, step, sign, area; // covers 2+ pixels if (x_top > x_bottom) { // flip scanline vertically; signed area is the same @@ -1976,29 +3152,79 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, dy = -dy; t = x0, x0 = xb, xb = t; } + STBTT_assert(dy >= 0); + STBTT_assert(dx >= 0); x1 = (int) x_top; x2 = (int) x_bottom; // compute intersection with y axis at x1+1 - y_crossing = (x1+1 - x0) * dy + y_top; + y_crossing = y_top + dy * (x1+1 - x0); + + // compute intersection with y axis at x2 + y_final = y_top + dy * (x2 - x0); + + // x1 x_top x2 x_bottom + // y_top +------|-----+------------+------------+--------|---+------------+ + // | | | | | | + // | | | | | | + // sy0 | Txxxxx|............|............|............|............| + // y_crossing | *xxxxx.......|............|............|............| + // | | xxxxx..|............|............|............| + // | | /- xx*xxxx........|............|............| + // | | dy < | xxxxxx..|............|............| + // y_final | | \- | xx*xxx.........|............| + // sy1 | | | | xxxxxB...|............| + // | | | | | | + // | | | | | | + // y_bottom +------------+------------+------------+------------+------------+ + // + // goal is to measure the area covered by '.' in each pixel + + // if x2 is right at the right edge of x1, y_crossing can blow up, github #1057 + // @TODO: maybe test against sy1 rather than y_bottom? + if (y_crossing > y_bottom) + y_crossing = y_bottom; sign = e->direction; - // area of the rectangle covered from y0..y_crossing + + // area of the rectangle covered from sy0..y_crossing area = sign * (y_crossing-sy0); - // area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) - scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2); - step = sign * dy; + // area of the triangle (x_top,sy0), (x1+1,sy0), (x1+1,y_crossing) + scanline[x1] += stbtt__sized_triangle_area(area, x1+1 - x_top); + + // check if final y_crossing is blown up; no test case for this + if (y_final > y_bottom) { + y_final = y_bottom; + dy = (y_final - y_crossing ) / (x2 - (x1+1)); // if denom=0, y_final = y_crossing, so y_final <= y_bottom + } + + // in second pixel, area covered by line segment found in first pixel + // is always a rectangle 1 wide * the height of that line segment; this + // is exactly what the variable 'area' stores. it also gets a contribution + // from the line segment within it. the THIRD pixel will get the first + // pixel's rectangle contribution, the second pixel's rectangle contribution, + // and its own contribution. the 'own contribution' is the same in every pixel except + // the leftmost and rightmost, a trapezoid that slides down in each pixel. + // the second pixel's contribution to the third pixel will be the + // rectangle 1 wide times the height change in the second pixel, which is dy. + + step = sign * dy * 1; // dy is dy/dx, change in y for every 1 change in x, + // which multiplied by 1-pixel-width is how much pixel area changes for each step in x + // so the area advances by 'step' every time + for (x = x1+1; x < x2; ++x) { - scanline[x] += area + step/2; + scanline[x] += area + step/2; // area of trapezoid is 1*step/2 area += step; } - y_crossing += dy * (x2 - (x1+1)); - - STBTT_assert(fabs(area) <= 1.01f); + STBTT_assert(STBTT_fabs(area) <= 1.01f); // accumulated error from area += step unless we round step down + STBTT_assert(sy1 > y_final-0.01f); - scanline[x2] += area + sign * (1-(x_bottom-x2)/2) * (sy1-y_crossing); + // area covered in the last pixel is the rectangle from all the pixels to the left, + // plus the trapezoid filled by the line segment in this pixel all the way to the right edge + scanline[x2] += area + sign * stbtt__position_trapezoid_area(sy1-y_final, (float) x2, x2+1.0f, x_bottom, x2+1.0f); + // the rest of the line is filled based on the total height of the line segment in this pixel scanline_fill[x2] += sign * (sy1-sy0); } } else { @@ -2006,6 +3232,9 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, // clipping logic. since this does not match the intended use // of this library, we use a different, very slow brute // force implementation + // note though that this does happen some of the time because + // x_top and x_bottom can be extrapolated at the top & bottom of + // the shape and actually lie outside the bounding box int x; for (x=0; x < len; ++x) { // cases: @@ -2021,19 +3250,18 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, // from the other y segment, and it might ignored as an empty segment. to avoid // that, we need to explicitly produce segments based on x positions. - // rename variables to clear pairs + // rename variables to clearly-defined pairs float y0 = y_top; float x1 = (float) (x); float x2 = (float) (x+1); float x3 = xb; float y3 = y_bottom; - float y1,y2; // x = e->x + e->dx * (y-y_top) // (y-y_top) = (x - e->x) / e->dx // y = (x - e->x) / e->dx + y_top - y1 = (x - x0) / dx + y_top; - y2 = (x+1 - x0) / dx + y_top; + float y1 = (x - x0) / dx + y_top; + float y2 = (x+1 - x0) / dx + y_top; if (x0 < x1 && x3 > x2) { // three segments descending down-right stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); @@ -2073,13 +3301,12 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int y,j=0, i; float scanline_data[129], *scanline, *scanline2; - if (result->w > 64) { + STBTT__NOTUSED(vsubsample); + + if (result->w > 64) scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata); - if (!scanline) - return; - } else { + else scanline = scanline_data; - } scanline2 = scanline + result->w; @@ -2113,12 +3340,18 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, while (e->y0 <= scan_y_bottom) { if (e->y0 != e->y1) { stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata); - if (!z) - return; - STBTT_assert(z->ey >= scan_y_top); - // insert at front - z->next = active; - active = z; + if (z != NULL) { + if (j == 0 && off_y != 0) { + if (z->ey < scan_y_top) { + // this can happen due to subpixel positioning and some kind of fp rounding error i think + z->ey = scan_y_top; + } + } + STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds + // insert at front + z->next = active; + active = z; + } } ++e; } @@ -2183,7 +3416,7 @@ static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n) static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n) { - /* threshhold for transitioning to insertion sort */ + /* threshold for transitioning to insertion sort */ while (n > 12) { stbtt__edge t; int c01,c12,c,m,i,j; @@ -2318,7 +3551,7 @@ static void stbtt__add_point(stbtt__point *points, int n, float x, float y) points[n].y = y; } -// tesselate until threshhold p is happy... @TODO warped to compensate for non-linear stretching +// tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n) { // midpoint @@ -2339,6 +3572,48 @@ static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x return 1; } +static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n) +{ + // @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough + float dx0 = x1-x0; + float dy0 = y1-y0; + float dx1 = x2-x1; + float dy1 = y2-y1; + float dx2 = x3-x2; + float dy2 = y3-y2; + float dx = x3-x0; + float dy = y3-y0; + float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2)); + float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy); + float flatness_squared = longlen*longlen-shortlen*shortlen; + + if (n > 16) // 65536 segments on one curve better be enough! + return; + + if (flatness_squared > objspace_flatness_squared) { + float x01 = (x0+x1)/2; + float y01 = (y0+y1)/2; + float x12 = (x1+x2)/2; + float y12 = (y1+y2)/2; + float x23 = (x2+x3)/2; + float y23 = (y2+y3)/2; + + float xa = (x01+x12)/2; + float ya = (y01+y12)/2; + float xb = (x12+x23)/2; + float yb = (y12+y23)/2; + + float mx = (xa+xb)/2; + float my = (ya+yb)/2; + + stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1); + stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1); + } else { + stbtt__add_point(points, *num_points,x3,y3); + *num_points = *num_points+1; + } +} + // returns number of contours static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) { @@ -2395,6 +3670,14 @@ static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, objspace_flatness_squared, 0); x = vertices[i].x, y = vertices[i].y; break; + case STBTT_vcubic: + stbtt__tesselate_cubic(points, &num_points, x,y, + vertices[i].cx, vertices[i].cy, + vertices[i].cx1, vertices[i].cy1, + vertices[i].x, vertices[i].y, + objspace_flatness_squared, 0); + x = vertices[i].x, y = vertices[i].y; + break; } } (*contour_lengths)[n] = num_points - start; @@ -2411,8 +3694,9 @@ error: STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) { - float scale = scale_x > scale_y ? scale_y : scale_x; - int winding_count, *winding_lengths; + float scale = scale_x > scale_y ? scale_y : scale_x; + int winding_count = 0; + int *winding_lengths = NULL; stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); if (windings) { stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata); @@ -2430,7 +3714,7 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info { int ix0,iy0,ix1,iy1; stbtt__bitmap gbm; - stbtt_vertex *vertices; + stbtt_vertex *vertices; int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); if (scale_x == 0) scale_x = scale_y; @@ -2453,7 +3737,7 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info if (height) *height = gbm.h; if (xoff ) *xoff = ix0; if (yoff ) *yoff = iy0; - + if (gbm.w && gbm.h) { gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata); if (gbm.pixels) { @@ -2464,7 +3748,7 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info } STBTT_free(vertices, info->userdata); return gbm.pixels; -} +} STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff) { @@ -2476,7 +3760,7 @@ STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigne int ix0,iy0; stbtt_vertex *vertices; int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); - stbtt__bitmap gbm; + stbtt__bitmap gbm; stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0); gbm.pixels = output; @@ -2498,7 +3782,12 @@ STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char * STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff) { return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff); -} +} + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint) +{ + stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint)); +} STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint) { @@ -2508,7 +3797,7 @@ STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, uns STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff) { return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff); -} +} STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint) { @@ -2521,7 +3810,7 @@ STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned ch // // This is SUPER-CRAPPY packing to keep source code small -STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) +static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) float pixel_height, // height of font in pixels unsigned char *pixels, int pw, int ph, // bitmap to be filled in int first_char, int num_chars, // characters to bake @@ -2530,6 +3819,7 @@ STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // fo float scale; int x,y,bottom_y, i; stbtt_fontinfo f; + f.userdata = NULL; if (!stbtt_InitFont(&f, data, offset)) return -1; STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels @@ -2566,11 +3856,11 @@ STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // fo return bottom_y; } -STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) { float d3d_bias = opengl_fillrule ? 0 : -0.5f; float ipw = 1.0f / pw, iph = 1.0f / ph; - stbtt_bakedchar *b = chardata + char_index; + const stbtt_bakedchar *b = chardata + char_index; int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f); int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f); @@ -2593,11 +3883,6 @@ STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int // #ifndef STB_RECT_PACK_VERSION -#ifdef _MSC_VER -#define STBTT__NOTUSED(v) (void)(v) -#else -#define STBTT__NOTUSED(v) (void)sizeof(v) -#endif typedef int stbrp_coord; @@ -2637,7 +3922,7 @@ static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *no con->y = 0; con->bottom_y = 0; STBTT__NOTUSED(nodes); - STBTT__NOTUSED(num_nodes); + STBTT__NOTUSED(num_nodes); } static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects) @@ -2691,6 +3976,7 @@ STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, in spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw; spc->h_oversample = 1; spc->v_oversample = 1; + spc->skip_missing = 0; stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes); @@ -2716,6 +4002,11 @@ STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h spc->v_oversample = v_oversample; } +STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip) +{ + spc->skip_missing = skip; +} + #define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1) static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) @@ -2723,6 +4014,7 @@ static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_i unsigned char buffer[STBTT_MAX_OVERSAMPLE]; int safe_w = w - kernel_width; int j; + STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze for (j=0; j < h; ++j) { int i; unsigned int total; @@ -2784,6 +4076,7 @@ static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_i unsigned char buffer[STBTT_MAX_OVERSAMPLE]; int safe_h = h - kernel_width; int j; + STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze for (j=0; j < w; ++j) { int i; unsigned int total; @@ -2853,9 +4146,10 @@ static float stbtt__oversample_shift(int oversample) } // rects array must be big enough to accommodate all characters in the given ranges -STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) +STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) { int i,j,k; + int missing_glyph_added = 0; k=0; for (i=0; i < num_ranges; ++i) { @@ -2867,13 +4161,19 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, stbtt_fon int x0,y0,x1,y1; int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; int glyph = stbtt_FindGlyphIndex(info, codepoint); - stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, - scale * spc->h_oversample, - scale * spc->v_oversample, - 0,0, - &x0,&y0,&x1,&y1); - rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); - rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); + if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) { + rects[k].w = rects[k].h = 0; + } else { + stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, + scale * spc->h_oversample, + scale * spc->v_oversample, + 0,0, + &x0,&y0,&x1,&y1); + rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); + rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); + if (glyph == 0) + missing_glyph_added = 1; + } ++k; } } @@ -2881,10 +4181,33 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, stbtt_fon return k; } +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph) +{ + stbtt_MakeGlyphBitmapSubpixel(info, + output, + out_w - (prefilter_x - 1), + out_h - (prefilter_y - 1), + out_stride, + scale_x, + scale_y, + shift_x, + shift_y, + glyph); + + if (prefilter_x > 1) + stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x); + + if (prefilter_y > 1) + stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y); + + *sub_x = stbtt__oversample_shift(prefilter_x); + *sub_y = stbtt__oversample_shift(prefilter_y); +} + // rects array must be big enough to accommodate all characters in the given ranges -STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) +STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) { - int i,j,k, return_value = 1; + int i,j,k, missing_glyph = -1, return_value = 1; // save current values int old_h_over = spc->h_oversample; @@ -2903,7 +4226,7 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, stbtt sub_y = stbtt__oversample_shift(spc->v_oversample); for (j=0; j < ranges[i].num_chars; ++j) { stbrp_rect *r = &rects[k]; - if (r->was_packed) { + if (r->was_packed && r->w != 0 && r->h != 0) { stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; int advance, lsb, x0,y0,x1,y1; int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; @@ -2949,6 +4272,13 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, stbtt bc->yoff = (float) y0 * recip_v + sub_y; bc->xoff2 = (x0 + r->w) * recip_h + sub_x; bc->yoff2 = (y0 + r->h) * recip_v + sub_y; + + if (glyph == 0) + missing_glyph = j; + } else if (spc->skip_missing) { + return_value = 0; + } else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) { + ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph]; } else { return_value = 0; // if any fail, report failure } @@ -2969,7 +4299,7 @@ STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects); } -STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) { stbtt_fontinfo info; int i,j,n, return_value = 1; @@ -2987,24 +4317,25 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontd n = 0; for (i=0; i < num_ranges; ++i) n += ranges[i].num_chars; - + rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); if (rects == NULL) return 0; + info.userdata = spc->user_allocator_context; stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index)); n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects); stbtt_PackFontRangesPackRects(spc, rects, n); - + return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects); STBTT_free(rects, spc->user_allocator_context); return return_value; } -STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size, +STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range) { stbtt_pack_range range; @@ -3016,10 +4347,23 @@ STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontda return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); } -STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) +STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap) +{ + int i_ascent, i_descent, i_lineGap; + float scale; + stbtt_fontinfo info; + stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index)); + scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size); + stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap); + *ascent = (float) i_ascent * scale; + *descent = (float) i_descent * scale; + *lineGap = (float) i_lineGap * scale; +} + +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) { float ipw = 1.0f / pw, iph = 1.0f / ph; - stbtt_packedchar *b = chardata + char_index; + const stbtt_packedchar *b = chardata + char_index; if (align_to_integer) { float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f); @@ -3043,6 +4387,385 @@ STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, i *xpos += b->xadvance; } +////////////////////////////////////////////////////////////////////////////// +// +// sdf computation +// + +#define STBTT_min(a,b) ((a) < (b) ? (a) : (b)) +#define STBTT_max(a,b) ((a) < (b) ? (b) : (a)) + +static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2]) +{ + float q0perp = q0[1]*ray[0] - q0[0]*ray[1]; + float q1perp = q1[1]*ray[0] - q1[0]*ray[1]; + float q2perp = q2[1]*ray[0] - q2[0]*ray[1]; + float roperp = orig[1]*ray[0] - orig[0]*ray[1]; + + float a = q0perp - 2*q1perp + q2perp; + float b = q1perp - q0perp; + float c = q0perp - roperp; + + float s0 = 0., s1 = 0.; + int num_s = 0; + + if (a != 0.0) { + float discr = b*b - a*c; + if (discr > 0.0) { + float rcpna = -1 / a; + float d = (float) STBTT_sqrt(discr); + s0 = (b+d) * rcpna; + s1 = (b-d) * rcpna; + if (s0 >= 0.0 && s0 <= 1.0) + num_s = 1; + if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) { + if (num_s == 0) s0 = s1; + ++num_s; + } + } + } else { + // 2*b*s + c = 0 + // s = -c / (2*b) + s0 = c / (-2 * b); + if (s0 >= 0.0 && s0 <= 1.0) + num_s = 1; + } + + if (num_s == 0) + return 0; + else { + float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]); + float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2; + + float q0d = q0[0]*rayn_x + q0[1]*rayn_y; + float q1d = q1[0]*rayn_x + q1[1]*rayn_y; + float q2d = q2[0]*rayn_x + q2[1]*rayn_y; + float rod = orig[0]*rayn_x + orig[1]*rayn_y; + + float q10d = q1d - q0d; + float q20d = q2d - q0d; + float q0rd = q0d - rod; + + hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d; + hits[0][1] = a*s0+b; + + if (num_s > 1) { + hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d; + hits[1][1] = a*s1+b; + return 2; + } else { + return 1; + } + } +} + +static int equal(float *a, float *b) +{ + return (a[0] == b[0] && a[1] == b[1]); +} + +static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts) +{ + int i; + float orig[2], ray[2] = { 1, 0 }; + float y_frac; + int winding = 0; + + // make sure y never passes through a vertex of the shape + y_frac = (float) STBTT_fmod(y, 1.0f); + if (y_frac < 0.01f) + y += 0.01f; + else if (y_frac > 0.99f) + y -= 0.01f; + + orig[0] = x; + orig[1] = y; + + // test a ray from (-infinity,y) to (x,y) + for (i=0; i < nverts; ++i) { + if (verts[i].type == STBTT_vline) { + int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y; + int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y; + if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { + float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; + if (x_inter < x) + winding += (y0 < y1) ? 1 : -1; + } + } + if (verts[i].type == STBTT_vcurve) { + int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ; + int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy; + int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ; + int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2)); + int by = STBTT_max(y0,STBTT_max(y1,y2)); + if (y > ay && y < by && x > ax) { + float q0[2],q1[2],q2[2]; + float hits[2][2]; + q0[0] = (float)x0; + q0[1] = (float)y0; + q1[0] = (float)x1; + q1[1] = (float)y1; + q2[0] = (float)x2; + q2[1] = (float)y2; + if (equal(q0,q1) || equal(q1,q2)) { + x0 = (int)verts[i-1].x; + y0 = (int)verts[i-1].y; + x1 = (int)verts[i ].x; + y1 = (int)verts[i ].y; + if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { + float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; + if (x_inter < x) + winding += (y0 < y1) ? 1 : -1; + } + } else { + int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits); + if (num_hits >= 1) + if (hits[0][0] < 0) + winding += (hits[0][1] < 0 ? -1 : 1); + if (num_hits >= 2) + if (hits[1][0] < 0) + winding += (hits[1][1] < 0 ? -1 : 1); + } + } + } + } + return winding; +} + +static float stbtt__cuberoot( float x ) +{ + if (x<0) + return -(float) STBTT_pow(-x,1.0f/3.0f); + else + return (float) STBTT_pow( x,1.0f/3.0f); +} + +// x^3 + a*x^2 + b*x + c = 0 +static int stbtt__solve_cubic(float a, float b, float c, float* r) +{ + float s = -a / 3; + float p = b - a*a / 3; + float q = a * (2*a*a - 9*b) / 27 + c; + float p3 = p*p*p; + float d = q*q + 4*p3 / 27; + if (d >= 0) { + float z = (float) STBTT_sqrt(d); + float u = (-q + z) / 2; + float v = (-q - z) / 2; + u = stbtt__cuberoot(u); + v = stbtt__cuberoot(v); + r[0] = s + u + v; + return 1; + } else { + float u = (float) STBTT_sqrt(-p/3); + float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative + float m = (float) STBTT_cos(v); + float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f; + r[0] = s + u * 2 * m; + r[1] = s - u * (m + n); + r[2] = s - u * (m - n); + + //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe? + //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f); + //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f); + return 3; + } +} + +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +{ + float scale_x = scale, scale_y = scale; + int ix0,iy0,ix1,iy1; + int w,h; + unsigned char *data; + + if (scale == 0) return NULL; + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1); + + // if empty, return NULL + if (ix0 == ix1 || iy0 == iy1) + return NULL; + + ix0 -= padding; + iy0 -= padding; + ix1 += padding; + iy1 += padding; + + w = (ix1 - ix0); + h = (iy1 - iy0); + + if (width ) *width = w; + if (height) *height = h; + if (xoff ) *xoff = ix0; + if (yoff ) *yoff = iy0; + + // invert for y-downwards bitmaps + scale_y = -scale_y; + + { + int x,y,i,j; + float *precompute; + stbtt_vertex *verts; + int num_verts = stbtt_GetGlyphShape(info, glyph, &verts); + data = (unsigned char *) STBTT_malloc(w * h, info->userdata); + precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata); + + for (i=0,j=num_verts-1; i < num_verts; j=i++) { + if (verts[i].type == STBTT_vline) { + float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; + float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y; + float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)); + precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist; + } else if (verts[i].type == STBTT_vcurve) { + float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y; + float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y; + float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y; + float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; + float len2 = bx*bx + by*by; + if (len2 != 0.0f) + precompute[i] = 1.0f / (bx*bx + by*by); + else + precompute[i] = 0.0f; + } else + precompute[i] = 0.0f; + } + + for (y=iy0; y < iy1; ++y) { + for (x=ix0; x < ix1; ++x) { + float val; + float min_dist = 999999.0f; + float sx = (float) x + 0.5f; + float sy = (float) y + 0.5f; + float x_gspace = (sx / scale_x); + float y_gspace = (sy / scale_y); + + int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); // @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path + + for (i=0; i < num_verts; ++i) { + float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; + + if (verts[i].type == STBTT_vline && precompute[i] != 0.0f) { + float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y; + + float dist,dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); + if (dist2 < min_dist*min_dist) + min_dist = (float) STBTT_sqrt(dist2); + + // coarse culling against bbox + //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist && + // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist) + dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i]; + STBTT_assert(i != 0); + if (dist < min_dist) { + // check position along line + // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0) + // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy) + float dx = x1-x0, dy = y1-y0; + float px = x0-sx, py = y0-sy; + // minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy + // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve + float t = -(px*dx + py*dy) / (dx*dx + dy*dy); + if (t >= 0.0f && t <= 1.0f) + min_dist = dist; + } + } else if (verts[i].type == STBTT_vcurve) { + float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y; + float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y; + float box_x0 = STBTT_min(STBTT_min(x0,x1),x2); + float box_y0 = STBTT_min(STBTT_min(y0,y1),y2); + float box_x1 = STBTT_max(STBTT_max(x0,x1),x2); + float box_y1 = STBTT_max(STBTT_max(y0,y1),y2); + // coarse culling against bbox to avoid computing cubic unnecessarily + if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) { + int num=0; + float ax = x1-x0, ay = y1-y0; + float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; + float mx = x0 - sx, my = y0 - sy; + float res[3] = {0.f,0.f,0.f}; + float px,py,t,it,dist2; + float a_inv = precompute[i]; + if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula + float a = 3*(ax*bx + ay*by); + float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by); + float c = mx*ax+my*ay; + if (a == 0.0) { // if a is 0, it's linear + if (b != 0.0) { + res[num++] = -c/b; + } + } else { + float discriminant = b*b - 4*a*c; + if (discriminant < 0) + num = 0; + else { + float root = (float) STBTT_sqrt(discriminant); + res[0] = (-b - root)/(2*a); + res[1] = (-b + root)/(2*a); + num = 2; // don't bother distinguishing 1-solution case, as code below will still work + } + } + } else { + float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point + float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv; + float d = (mx*ax+my*ay) * a_inv; + num = stbtt__solve_cubic(b, c, d, res); + } + dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); + if (dist2 < min_dist*min_dist) + min_dist = (float) STBTT_sqrt(dist2); + + if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) { + t = res[0], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) { + t = res[1], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) { + t = res[2], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + } + } + } + if (winding == 0) + min_dist = -min_dist; // if outside the shape, value is negative + val = onedge_value + pixel_dist_scale * min_dist; + if (val < 0) + val = 0; + else if (val > 255) + val = 255; + data[(y-iy0)*w+(x-ix0)] = (unsigned char) val; + } + } + STBTT_free(precompute, info->userdata); + STBTT_free(verts, info->userdata); + } + return data; +} + +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff); +} + +STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata) +{ + STBTT_free(bitmap, userdata); +} ////////////////////////////////////////////////////////////////////////////// // @@ -3050,7 +4773,7 @@ STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, i // // check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string -static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(const stbtt_uint8 *s1, stbtt_int32 len1, const stbtt_uint8 *s2, stbtt_int32 len2) +static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) { stbtt_int32 i=0; @@ -3089,9 +4812,9 @@ static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(const stbtt_uint8 return i; } -STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) +static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2) { - return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((const stbtt_uint8*) s1, len1, (const stbtt_uint8*) s2, len2); + return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2); } // returns results in whatever encoding you request... but note that 2-byte encodings @@ -3147,7 +4870,7 @@ static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, return 1; } else if (matchlen < nlen && name[matchlen] == ' ') { ++matchlen; - if (stbtt_CompareUTF8toUTF16_bigendian((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen)) + if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen)) return 1; } } else { @@ -3193,7 +4916,7 @@ static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *nam return 0; } -STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *font_collection, const char *name_utf8, stbtt_int32 flags) +static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags) { stbtt_int32 i; for (i=0;;++i) { @@ -3204,11 +4927,71 @@ STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *font_collection, const } } +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif + +STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, + float pixel_height, unsigned char *pixels, int pw, int ph, + int first_char, int num_chars, stbtt_bakedchar *chardata) +{ + return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata); +} + +STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index) +{ + return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index); +} + +STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data) +{ + return stbtt_GetNumberOfFonts_internal((unsigned char *) data); +} + +STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset) +{ + return stbtt_InitFont_internal(info, (unsigned char *) data, offset); +} + +STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags) +{ + return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags); +} + +STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) +{ + return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2); +} + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif + #endif // STB_TRUETYPE_IMPLEMENTATION // FULL VERSION HISTORY // +// 1.25 (2021-07-11) many fixes +// 1.24 (2020-02-05) fix warning +// 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) +// 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined +// 1.21 (2019-02-25) fix warning +// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() +// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod +// 1.18 (2018-01-29) add missing function +// 1.17 (2017-07-23) make more arguments const; doc fix +// 1.16 (2017-07-12) SDF support +// 1.15 (2017-03-03) make more arguments const +// 1.14 (2017-01-16) num-fonts-in-TTC function +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts +// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual +// 1.11 (2016-04-02) fix unused-variable warning +// 1.10 (2016-04-02) allow user-defined fabs() replacement +// fix memory leak if fontsize=0.0 +// fix warning from duplicate typedef +// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges // 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; // allow PackFontRanges to pack and render in separate phases; @@ -3250,3 +5033,45 @@ STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *font_collection, const // 0.2 (2009-03-11) Fix unsigned/signed char warnings // 0.1 (2009-03-09) First public release // + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +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. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +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 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. +------------------------------------------------------------------------------ +*/ diff --git a/test/dm/video.c b/test/dm/video.c index 6d9c55c14035..0534ee93a3d4 100644 --- a/test/dm/video.c +++ b/test/dm/video.c @@ -556,7 +556,7 @@ static int dm_test_video_truetype(struct unit_test_state *uts) ut_assertok(video_get_nologo(uts, &dev)); ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); vidconsole_put_string(con, test_string); - ut_asserteq(12187, compress_frame_buffer(uts, dev)); + ut_asserteq(12174, compress_frame_buffer(uts, dev)); return 0; } @@ -577,7 +577,7 @@ static int dm_test_video_truetype_scroll(struct unit_test_state *uts) ut_assertok(video_get_nologo(uts, &dev)); ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); vidconsole_put_string(con, test_string); - ut_asserteq(34481, compress_frame_buffer(uts, dev)); + ut_asserteq(34287, compress_frame_buffer(uts, dev)); return 0; } @@ -598,7 +598,7 @@ static int dm_test_video_truetype_bs(struct unit_test_state *uts) ut_assertok(video_get_nologo(uts, &dev)); ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); vidconsole_put_string(con, test_string); - ut_asserteq(29579, compress_frame_buffer(uts, dev)); + ut_asserteq(29471, compress_frame_buffer(uts, dev)); return 0; }