xref: /aosp_15_r20/external/angle/src/libANGLE/gen_overlay_widgets.py (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker#! /usr/bin/python3
2*8975f5c5SAndroid Build Coastguard Worker
3*8975f5c5SAndroid Build Coastguard Worker# Copyright 2019 The ANGLE Project Authors. All rights reserved.
4*8975f5c5SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be
5*8975f5c5SAndroid Build Coastguard Worker# found in the LICENSE file.
6*8975f5c5SAndroid Build Coastguard Worker#
7*8975f5c5SAndroid Build Coastguard Worker# gen_overlay_widgets.py:
8*8975f5c5SAndroid Build Coastguard Worker#  Code generation for overlay widgets.  Should be run when the widgets declaration file,
9*8975f5c5SAndroid Build Coastguard Worker#  overlay_widgets.json, is changed.
10*8975f5c5SAndroid Build Coastguard Worker#  NOTE: don't run this script directly. Run scripts/run_code_generation.py.
11*8975f5c5SAndroid Build Coastguard Worker
12*8975f5c5SAndroid Build Coastguard Workerimport json
13*8975f5c5SAndroid Build Coastguard Workerimport os
14*8975f5c5SAndroid Build Coastguard Workerimport sys
15*8975f5c5SAndroid Build Coastguard Worker
16*8975f5c5SAndroid Build Coastguard WorkerOUT_SOURCE_FILE_NAME = 'Overlay_autogen.cpp'
17*8975f5c5SAndroid Build Coastguard WorkerOUT_HEADER_FILE_NAME = 'Overlay_autogen.h'
18*8975f5c5SAndroid Build Coastguard Worker
19*8975f5c5SAndroid Build Coastguard WorkerIN_JSON_FILE_NAME = 'overlay_widgets.json'
20*8975f5c5SAndroid Build Coastguard Worker
21*8975f5c5SAndroid Build Coastguard WorkerOUT_SOURCE_FILE_TEMPLATE = u"""// GENERATED FILE - DO NOT EDIT.
22*8975f5c5SAndroid Build Coastguard Worker// Generated by {script_name} using data from {input_file_name}.
23*8975f5c5SAndroid Build Coastguard Worker//
24*8975f5c5SAndroid Build Coastguard Worker// Copyright 2019 The ANGLE Project Authors. All rights reserved.
25*8975f5c5SAndroid Build Coastguard Worker// Use of this source code is governed by a BSD-style license that can be
26*8975f5c5SAndroid Build Coastguard Worker// found in the LICENSE file.
27*8975f5c5SAndroid Build Coastguard Worker//
28*8975f5c5SAndroid Build Coastguard Worker// {out_file_name}:
29*8975f5c5SAndroid Build Coastguard Worker//   Autogenerated overlay widget declarations.
30*8975f5c5SAndroid Build Coastguard Worker
31*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/renderer/driver_utils.h"
32*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/Overlay.h"
33*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/OverlayWidgets.h"
34*8975f5c5SAndroid Build Coastguard Worker#include "libANGLE/Overlay_font_autogen.h"
35*8975f5c5SAndroid Build Coastguard Worker
36*8975f5c5SAndroid Build Coastguard Workernamespace gl
37*8975f5c5SAndroid Build Coastguard Worker{{
38*8975f5c5SAndroid Build Coastguard Workerusing namespace overlay;
39*8975f5c5SAndroid Build Coastguard Worker
40*8975f5c5SAndroid Build Coastguard Workernamespace
41*8975f5c5SAndroid Build Coastguard Worker{{
42*8975f5c5SAndroid Build Coastguard Workerint GetFontSize(int fontSize, bool largeFont)
43*8975f5c5SAndroid Build Coastguard Worker{{
44*8975f5c5SAndroid Build Coastguard Worker    if (largeFont && fontSize > 0)
45*8975f5c5SAndroid Build Coastguard Worker    {{
46*8975f5c5SAndroid Build Coastguard Worker        return fontSize - 1;
47*8975f5c5SAndroid Build Coastguard Worker    }}
48*8975f5c5SAndroid Build Coastguard Worker    return fontSize;
49*8975f5c5SAndroid Build Coastguard Worker}}
50*8975f5c5SAndroid Build Coastguard Worker}}  // anonymous namespace
51*8975f5c5SAndroid Build Coastguard Worker
52*8975f5c5SAndroid Build Coastguard Workervoid Overlay::initOverlayWidgets()
53*8975f5c5SAndroid Build Coastguard Worker{{
54*8975f5c5SAndroid Build Coastguard Worker    const bool kLargeFont = rx::IsAndroid();
55*8975f5c5SAndroid Build Coastguard Worker
56*8975f5c5SAndroid Build Coastguard Worker    {init_widgets}
57*8975f5c5SAndroid Build Coastguard Worker}}
58*8975f5c5SAndroid Build Coastguard Worker
59*8975f5c5SAndroid Build Coastguard Worker}}  // namespace gl
60*8975f5c5SAndroid Build Coastguard Worker
61*8975f5c5SAndroid Build Coastguard Worker"""
62*8975f5c5SAndroid Build Coastguard Worker
63*8975f5c5SAndroid Build Coastguard WorkerOUT_HEADER_FILE_TEMPLATE = u"""// GENERATED FILE - DO NOT EDIT.
64*8975f5c5SAndroid Build Coastguard Worker// Generated by {script_name} using data from {input_file_name}.
65*8975f5c5SAndroid Build Coastguard Worker//
66*8975f5c5SAndroid Build Coastguard Worker// Copyright 2019 The ANGLE Project Authors. All rights reserved.
67*8975f5c5SAndroid Build Coastguard Worker// Use of this source code is governed by a BSD-style license that can be
68*8975f5c5SAndroid Build Coastguard Worker// found in the LICENSE file.
69*8975f5c5SAndroid Build Coastguard Worker//
70*8975f5c5SAndroid Build Coastguard Worker// {out_file_name}:
71*8975f5c5SAndroid Build Coastguard Worker//   Autogenerated overlay widget declarations.
72*8975f5c5SAndroid Build Coastguard Worker
73*8975f5c5SAndroid Build Coastguard Workernamespace gl
74*8975f5c5SAndroid Build Coastguard Worker{{
75*8975f5c5SAndroid Build Coastguard Workerenum class WidgetId
76*8975f5c5SAndroid Build Coastguard Worker{{
77*8975f5c5SAndroid Build Coastguard Worker{widget_ids}
78*8975f5c5SAndroid Build Coastguard Worker    InvalidEnum,
79*8975f5c5SAndroid Build Coastguard Worker    EnumCount = InvalidEnum,
80*8975f5c5SAndroid Build Coastguard Worker}};
81*8975f5c5SAndroid Build Coastguard Worker
82*8975f5c5SAndroid Build Coastguard Worker// We can use this "X" macro to generate multiple code patterns.
83*8975f5c5SAndroid Build Coastguard Worker#define ANGLE_WIDGET_ID_X(PROC) \
84*8975f5c5SAndroid Build Coastguard Worker{widget_x_defs}
85*8975f5c5SAndroid Build Coastguard Worker
86*8975f5c5SAndroid Build Coastguard Worker}}  // namespace gl
87*8975f5c5SAndroid Build Coastguard Worker"""
88*8975f5c5SAndroid Build Coastguard Worker
89*8975f5c5SAndroid Build Coastguard WorkerWIDGET_INIT_TEMPLATE = u"""{{
90*8975f5c5SAndroid Build Coastguard Workerconst int32_t fontSize = GetFontSize({font_size}, kLargeFont);
91*8975f5c5SAndroid Build Coastguard Workerconst int32_t offsetX = {offset_x};
92*8975f5c5SAndroid Build Coastguard Workerconst int32_t offsetY = {offset_y};
93*8975f5c5SAndroid Build Coastguard Workerconst int32_t width = {width};
94*8975f5c5SAndroid Build Coastguard Workerconst int32_t height = {height};
95*8975f5c5SAndroid Build Coastguard Worker
96*8975f5c5SAndroid Build Coastguard Workerwidget->{subwidget}type          = WidgetType::{type};
97*8975f5c5SAndroid Build Coastguard Workerwidget->{subwidget}fontSize      = fontSize;
98*8975f5c5SAndroid Build Coastguard Workerwidget->{subwidget}coords[0]     = {coord0};
99*8975f5c5SAndroid Build Coastguard Workerwidget->{subwidget}coords[1]     = {coord1};
100*8975f5c5SAndroid Build Coastguard Workerwidget->{subwidget}coords[2]     = {coord2};
101*8975f5c5SAndroid Build Coastguard Workerwidget->{subwidget}coords[3]     = {coord3};
102*8975f5c5SAndroid Build Coastguard Workerwidget->{subwidget}color[0]      = {color_r}f;
103*8975f5c5SAndroid Build Coastguard Workerwidget->{subwidget}color[1]      = {color_g}f;
104*8975f5c5SAndroid Build Coastguard Workerwidget->{subwidget}color[2]      = {color_b}f;
105*8975f5c5SAndroid Build Coastguard Workerwidget->{subwidget}color[3]      = {color_a}f;
106*8975f5c5SAndroid Build Coastguard Workerwidget->{subwidget}matchToWidget = {match_to};
107*8975f5c5SAndroid Build Coastguard Worker}}
108*8975f5c5SAndroid Build Coastguard Worker"""
109*8975f5c5SAndroid Build Coastguard Worker
110*8975f5c5SAndroid Build Coastguard WorkerWIDGET_ID_TEMPLATE = """    // {comment}
111*8975f5c5SAndroid Build Coastguard Worker    {name},
112*8975f5c5SAndroid Build Coastguard Worker"""
113*8975f5c5SAndroid Build Coastguard Worker
114*8975f5c5SAndroid Build Coastguard Worker
115*8975f5c5SAndroid Build Coastguard Workerdef extract_type_and_constructor(properties):
116*8975f5c5SAndroid Build Coastguard Worker    constructor = properties['type']
117*8975f5c5SAndroid Build Coastguard Worker    args_separated = constructor.split('(', 1)
118*8975f5c5SAndroid Build Coastguard Worker    if len(args_separated) == 1:
119*8975f5c5SAndroid Build Coastguard Worker        return constructor, constructor
120*8975f5c5SAndroid Build Coastguard Worker
121*8975f5c5SAndroid Build Coastguard Worker    type_no_constructor = args_separated[0]
122*8975f5c5SAndroid Build Coastguard Worker    return type_no_constructor, constructor
123*8975f5c5SAndroid Build Coastguard Worker
124*8975f5c5SAndroid Build Coastguard Worker
125*8975f5c5SAndroid Build Coastguard Workerdef get_font_size_constant(properties):
126*8975f5c5SAndroid Build Coastguard Worker    return 'kFontMip' + properties['font'].capitalize()
127*8975f5c5SAndroid Build Coastguard Worker
128*8975f5c5SAndroid Build Coastguard Worker
129*8975f5c5SAndroid Build Coastguard Workerdef is_graph_type(type):
130*8975f5c5SAndroid Build Coastguard Worker    return type == 'RunningGraph' or type == 'RunningHistogram'
131*8975f5c5SAndroid Build Coastguard Worker
132*8975f5c5SAndroid Build Coastguard Worker
133*8975f5c5SAndroid Build Coastguard Workerdef is_text_type(type):
134*8975f5c5SAndroid Build Coastguard Worker    return not is_graph_type(type)
135*8975f5c5SAndroid Build Coastguard Worker
136*8975f5c5SAndroid Build Coastguard Worker
137*8975f5c5SAndroid Build Coastguard Workerclass OverlayWidget:
138*8975f5c5SAndroid Build Coastguard Worker
139*8975f5c5SAndroid Build Coastguard Worker    def __init__(self, properties, is_graph_description=False):
140*8975f5c5SAndroid Build Coastguard Worker        if not is_graph_description:
141*8975f5c5SAndroid Build Coastguard Worker            self.name = properties['name']
142*8975f5c5SAndroid Build Coastguard Worker        self.type, self.constructor = extract_type_and_constructor(properties)
143*8975f5c5SAndroid Build Coastguard Worker        self.extract_common(properties)
144*8975f5c5SAndroid Build Coastguard Worker
145*8975f5c5SAndroid Build Coastguard Worker        if is_graph_type(self.type):
146*8975f5c5SAndroid Build Coastguard Worker            description_properties = properties['description']
147*8975f5c5SAndroid Build Coastguard Worker            description_properties['type'] = 'Text'
148*8975f5c5SAndroid Build Coastguard Worker            self.description = OverlayWidget(description_properties, True)
149*8975f5c5SAndroid Build Coastguard Worker
150*8975f5c5SAndroid Build Coastguard Worker    def extract_common(self, properties):
151*8975f5c5SAndroid Build Coastguard Worker        self.color = properties['color']
152*8975f5c5SAndroid Build Coastguard Worker        self.coords = properties['coords']
153*8975f5c5SAndroid Build Coastguard Worker        self.match_to = properties.get('match_to', None)
154*8975f5c5SAndroid Build Coastguard Worker        if is_graph_type(self.type):
155*8975f5c5SAndroid Build Coastguard Worker            self.bar_width = properties['bar_width']
156*8975f5c5SAndroid Build Coastguard Worker            self.height = properties['height']
157*8975f5c5SAndroid Build Coastguard Worker        else:
158*8975f5c5SAndroid Build Coastguard Worker            self.font = get_font_size_constant(properties)
159*8975f5c5SAndroid Build Coastguard Worker            self.length = properties['length']
160*8975f5c5SAndroid Build Coastguard Worker
161*8975f5c5SAndroid Build Coastguard Worker        self.negative_alignment = [False, False]
162*8975f5c5SAndroid Build Coastguard Worker
163*8975f5c5SAndroid Build Coastguard Worker
164*8975f5c5SAndroid Build Coastguard Workerdef get_relative_coord_widget(coord, widgets_so_far):
165*8975f5c5SAndroid Build Coastguard Worker    if not isinstance(coord, str):
166*8975f5c5SAndroid Build Coastguard Worker        return None
167*8975f5c5SAndroid Build Coastguard Worker
168*8975f5c5SAndroid Build Coastguard Worker    coord_split = coord.split('.')
169*8975f5c5SAndroid Build Coastguard Worker    widget = widgets_so_far[coord_split[0]]
170*8975f5c5SAndroid Build Coastguard Worker    if len(coord_split) > 3:
171*8975f5c5SAndroid Build Coastguard Worker        widget = widget.description
172*8975f5c5SAndroid Build Coastguard Worker
173*8975f5c5SAndroid Build Coastguard Worker    return widget
174*8975f5c5SAndroid Build Coastguard Worker
175*8975f5c5SAndroid Build Coastguard Worker
176*8975f5c5SAndroid Build Coastguard Workerdef parse_relative_coord(coord):
177*8975f5c5SAndroid Build Coastguard Worker
178*8975f5c5SAndroid Build Coastguard Worker    # The input coordinate (widget.coord[axis]) is either:
179*8975f5c5SAndroid Build Coastguard Worker    #
180*8975f5c5SAndroid Build Coastguard Worker    # - a number
181*8975f5c5SAndroid Build Coastguard Worker    # - other_widget.edge.mode:
182*8975f5c5SAndroid Build Coastguard Worker    #   * edge is in {left, right} or {top, bottom} based on axis
183*8975f5c5SAndroid Build Coastguard Worker    #   * mode is in {align, adjacent}
184*8975f5c5SAndroid Build Coastguard Worker    # - other_widget.desc.edge.mode: this is similar to other_widget.edge.mode, except
185*8975f5c5SAndroid Build Coastguard Worker    #                                it refers to a graph widget's description widget
186*8975f5c5SAndroid Build Coastguard Worker    #
187*8975f5c5SAndroid Build Coastguard Worker    # This function parses the last two possibilities.
188*8975f5c5SAndroid Build Coastguard Worker    if not isinstance(coord, str):
189*8975f5c5SAndroid Build Coastguard Worker        return None, None, None
190*8975f5c5SAndroid Build Coastguard Worker
191*8975f5c5SAndroid Build Coastguard Worker    coord_split = coord.split('.')
192*8975f5c5SAndroid Build Coastguard Worker    coords_expr = 'mState.mOverlayWidgets[WidgetId::' + coord_split[0] + ']'
193*8975f5c5SAndroid Build Coastguard Worker    if len(coord_split) > 3:
194*8975f5c5SAndroid Build Coastguard Worker        assert len(coord_split) == 4 and coord_split[1] == 'desc'
195*8975f5c5SAndroid Build Coastguard Worker        coords_expr += '->getDescriptionWidget()'
196*8975f5c5SAndroid Build Coastguard Worker    coords_expr += '->coords'
197*8975f5c5SAndroid Build Coastguard Worker
198*8975f5c5SAndroid Build Coastguard Worker    edge = coord_split[-2]
199*8975f5c5SAndroid Build Coastguard Worker    mode = coord_split[-1]
200*8975f5c5SAndroid Build Coastguard Worker
201*8975f5c5SAndroid Build Coastguard Worker    return coords_expr, edge, mode
202*8975f5c5SAndroid Build Coastguard Worker
203*8975f5c5SAndroid Build Coastguard Worker
204*8975f5c5SAndroid Build Coastguard Workerdef is_negative_coord(coords, axis, widgets_so_far):
205*8975f5c5SAndroid Build Coastguard Worker
206*8975f5c5SAndroid Build Coastguard Worker    other_widget = get_relative_coord_widget(coords[axis], widgets_so_far)
207*8975f5c5SAndroid Build Coastguard Worker    if other_widget is not None:
208*8975f5c5SAndroid Build Coastguard Worker        # We simply need to know if other_widget's coordinate is negative or not.
209*8975f5c5SAndroid Build Coastguard Worker        return other_widget.negative_alignment[axis]
210*8975f5c5SAndroid Build Coastguard Worker
211*8975f5c5SAndroid Build Coastguard Worker    return coords[axis] < 0
212*8975f5c5SAndroid Build Coastguard Worker
213*8975f5c5SAndroid Build Coastguard Worker
214*8975f5c5SAndroid Build Coastguard Workerdef set_alignment_flags(overlay_widget, widgets_so_far):
215*8975f5c5SAndroid Build Coastguard Worker    overlay_widget.negative_alignment[0] = is_negative_coord(overlay_widget.coords, 0,
216*8975f5c5SAndroid Build Coastguard Worker                                                             widgets_so_far)
217*8975f5c5SAndroid Build Coastguard Worker    overlay_widget.negative_alignment[1] = is_negative_coord(overlay_widget.coords, 1,
218*8975f5c5SAndroid Build Coastguard Worker                                                             widgets_so_far)
219*8975f5c5SAndroid Build Coastguard Worker
220*8975f5c5SAndroid Build Coastguard Worker    if is_graph_type(overlay_widget.type):
221*8975f5c5SAndroid Build Coastguard Worker        set_alignment_flags(overlay_widget.description, widgets_so_far)
222*8975f5c5SAndroid Build Coastguard Worker
223*8975f5c5SAndroid Build Coastguard Worker
224*8975f5c5SAndroid Build Coastguard Workerdef get_offset_helper(widget, axis, smaller_coord_side):
225*8975f5c5SAndroid Build Coastguard Worker    # Assume axis is X.  This function returns two values:
226*8975f5c5SAndroid Build Coastguard Worker    # - An offset where the bounding box is placed at,
227*8975f5c5SAndroid Build Coastguard Worker    # - Whether this offset is for the left or right edge.
228*8975f5c5SAndroid Build Coastguard Worker    #
229*8975f5c5SAndroid Build Coastguard Worker    # The input coordinate (widget.coord[axis]) is either:
230*8975f5c5SAndroid Build Coastguard Worker    #
231*8975f5c5SAndroid Build Coastguard Worker    # - a number: in this case, the offset is that number, and its sign
232*8975f5c5SAndroid Build Coastguard Worker    #             determines whether this refers to the left or right edge of
233*8975f5c5SAndroid Build Coastguard Worker    #             the bounding box.
234*8975f5c5SAndroid Build Coastguard Worker    # - other_widget[.desc].edge.mode: this has multiple possibilities:
235*8975f5c5SAndroid Build Coastguard Worker    #   * edge=left, mode=align: the offset is other_widget[.desc].left, the edge is left.
236*8975f5c5SAndroid Build Coastguard Worker    #   * edge=left, mode=adjacent: the offset is other_widget[.desc].left, the edge is right.
237*8975f5c5SAndroid Build Coastguard Worker    #   * edge=right, mode=align: the offset is other_widget[.desc].right, the edge is right.
238*8975f5c5SAndroid Build Coastguard Worker    #   * edge=right, mode=adjacent: the offset is other_widget[.desc].right, the edge is left.
239*8975f5c5SAndroid Build Coastguard Worker    #
240*8975f5c5SAndroid Build Coastguard Worker    # The case for the Y axis is similar, with the edge values being top or bottom.
241*8975f5c5SAndroid Build Coastguard Worker
242*8975f5c5SAndroid Build Coastguard Worker    coord = widget.coords[axis]
243*8975f5c5SAndroid Build Coastguard Worker
244*8975f5c5SAndroid Build Coastguard Worker    other_coords_expr, relative_edge, relative_mode = parse_relative_coord(coord)
245*8975f5c5SAndroid Build Coastguard Worker    if other_coords_expr is None:
246*8975f5c5SAndroid Build Coastguard Worker        is_left = coord >= 0
247*8975f5c5SAndroid Build Coastguard Worker        return coord, is_left
248*8975f5c5SAndroid Build Coastguard Worker
249*8975f5c5SAndroid Build Coastguard Worker    is_left = relative_edge == smaller_coord_side
250*8975f5c5SAndroid Build Coastguard Worker    is_align = relative_mode == 'align'
251*8975f5c5SAndroid Build Coastguard Worker
252*8975f5c5SAndroid Build Coastguard Worker    other_widget_coord_index = axis + (0 if is_left else 2)
253*8975f5c5SAndroid Build Coastguard Worker    offset = other_coords_expr + '[' + str(other_widget_coord_index) + ']'
254*8975f5c5SAndroid Build Coastguard Worker
255*8975f5c5SAndroid Build Coastguard Worker    return offset, is_left == is_align
256*8975f5c5SAndroid Build Coastguard Worker
257*8975f5c5SAndroid Build Coastguard Worker
258*8975f5c5SAndroid Build Coastguard Workerdef get_offset_x(widget):
259*8975f5c5SAndroid Build Coastguard Worker    return get_offset_helper(widget, 0, 'left')
260*8975f5c5SAndroid Build Coastguard Worker
261*8975f5c5SAndroid Build Coastguard Worker
262*8975f5c5SAndroid Build Coastguard Workerdef get_offset_y(widget):
263*8975f5c5SAndroid Build Coastguard Worker    return get_offset_helper(widget, 1, 'top')
264*8975f5c5SAndroid Build Coastguard Worker
265*8975f5c5SAndroid Build Coastguard Worker
266*8975f5c5SAndroid Build Coastguard Workerdef get_bounding_box_coords(offset, width, offset_is_left, is_left_aligned):
267*8975f5c5SAndroid Build Coastguard Worker    # See comment in generate_widget_init_helper.  This function is implementing the following:
268*8975f5c5SAndroid Build Coastguard Worker    #
269*8975f5c5SAndroid Build Coastguard Worker    # -  offset_is_left &&  is_left_aligned: [offset, offset + width]
270*8975f5c5SAndroid Build Coastguard Worker    # -  offset_is_left && !is_left_aligned: [offset, std::min(offset + width, -1)]
271*8975f5c5SAndroid Build Coastguard Worker    # - !offset_is_left &&  is_left_aligned: [std::max(1, offset - width), offset]
272*8975f5c5SAndroid Build Coastguard Worker    # - !offset_is_left && !is_left_aligned: [offset - width, offset]
273*8975f5c5SAndroid Build Coastguard Worker
274*8975f5c5SAndroid Build Coastguard Worker    coord_left = offset if offset_is_left else (offset + ' - ' + width)
275*8975f5c5SAndroid Build Coastguard Worker    coord_right = (offset + ' + ' + width) if offset_is_left else offset
276*8975f5c5SAndroid Build Coastguard Worker
277*8975f5c5SAndroid Build Coastguard Worker    if offset_is_left and not is_left_aligned:
278*8975f5c5SAndroid Build Coastguard Worker        coord_right = 'std::min(' + coord_right + ', -1)'
279*8975f5c5SAndroid Build Coastguard Worker    if not offset_is_left and is_left_aligned:
280*8975f5c5SAndroid Build Coastguard Worker        coord_left = 'std::max(' + coord_left + ', 1)'
281*8975f5c5SAndroid Build Coastguard Worker
282*8975f5c5SAndroid Build Coastguard Worker    return coord_left, coord_right
283*8975f5c5SAndroid Build Coastguard Worker
284*8975f5c5SAndroid Build Coastguard Worker
285*8975f5c5SAndroid Build Coastguard Workerdef generate_widget_init_helper(widget, is_graph_description=False):
286*8975f5c5SAndroid Build Coastguard Worker    font_size = '0'
287*8975f5c5SAndroid Build Coastguard Worker
288*8975f5c5SAndroid Build Coastguard Worker    # Common attributes
289*8975f5c5SAndroid Build Coastguard Worker    color = [channel / 255.0 for channel in widget.color]
290*8975f5c5SAndroid Build Coastguard Worker    offset_x, offset_x_is_left = get_offset_x(widget)
291*8975f5c5SAndroid Build Coastguard Worker    offset_y, offset_y_is_top = get_offset_y(widget)
292*8975f5c5SAndroid Build Coastguard Worker
293*8975f5c5SAndroid Build Coastguard Worker    if is_text_type(widget.type):
294*8975f5c5SAndroid Build Coastguard Worker        # Attributes deriven from text properties
295*8975f5c5SAndroid Build Coastguard Worker        font_size = widget.font
296*8975f5c5SAndroid Build Coastguard Worker        width = str(widget.length) + ' * (kFontGlyphWidth >> fontSize)'
297*8975f5c5SAndroid Build Coastguard Worker        height = '(kFontGlyphHeight >> fontSize)'
298*8975f5c5SAndroid Build Coastguard Worker    else:
299*8975f5c5SAndroid Build Coastguard Worker        # Attributes deriven from graph properties
300*8975f5c5SAndroid Build Coastguard Worker        width = str(widget.bar_width) + ' * static_cast<uint32_t>(widget->runningValues.size())'
301*8975f5c5SAndroid Build Coastguard Worker        height = widget.height
302*8975f5c5SAndroid Build Coastguard Worker
303*8975f5c5SAndroid Build Coastguard Worker    is_left_aligned = not widget.negative_alignment[0]
304*8975f5c5SAndroid Build Coastguard Worker    is_top_aligned = not widget.negative_alignment[1]
305*8975f5c5SAndroid Build Coastguard Worker
306*8975f5c5SAndroid Build Coastguard Worker    # We have offset_x, offset_y, width and height which together determine the bounding box.  If
307*8975f5c5SAndroid Build Coastguard Worker    # offset_x_is_left, the bounding box X would be in [offset_x, offset_x + width], otherwise it
308*8975f5c5SAndroid Build Coastguard Worker    # would be in [offset_x - width, offset_x].  Similarly for y.  Since we use negative values to
309*8975f5c5SAndroid Build Coastguard Worker    # mean aligned to the right side of the screen, we need to make sure that:
310*8975f5c5SAndroid Build Coastguard Worker    #
311*8975f5c5SAndroid Build Coastguard Worker    # - if left aligned: offset_x - width is at minimum 1
312*8975f5c5SAndroid Build Coastguard Worker    # - if right aligned: offset_x + width is at maximum -1
313*8975f5c5SAndroid Build Coastguard Worker    #
314*8975f5c5SAndroid Build Coastguard Worker    # We therefore have the following combinations for the X axis:
315*8975f5c5SAndroid Build Coastguard Worker    #
316*8975f5c5SAndroid Build Coastguard Worker    # -  offset_x_is_left &&  is_left_aligned: [offset_x, offset_x + width]
317*8975f5c5SAndroid Build Coastguard Worker    # -  offset_x_is_left && !is_left_aligned: [offset_x, std::min(offset_x + width, -1)]
318*8975f5c5SAndroid Build Coastguard Worker    # - !offset_x_is_left &&  is_left_aligned: [std::max(1, offset_x - width), offset_x]
319*8975f5c5SAndroid Build Coastguard Worker    # - !offset_x_is_left && !is_left_aligned: [offset_x - width, offset_x]
320*8975f5c5SAndroid Build Coastguard Worker    #
321*8975f5c5SAndroid Build Coastguard Worker    # Similarly for y.
322*8975f5c5SAndroid Build Coastguard Worker    coord0, coord2 = get_bounding_box_coords('offsetX', 'width', offset_x_is_left, is_left_aligned)
323*8975f5c5SAndroid Build Coastguard Worker    coord1, coord3 = get_bounding_box_coords('offsetY', 'height', offset_y_is_top, is_top_aligned)
324*8975f5c5SAndroid Build Coastguard Worker
325*8975f5c5SAndroid Build Coastguard Worker    match_to = 'nullptr' if widget.match_to is None else \
326*8975f5c5SAndroid Build Coastguard Worker               'mState.mOverlayWidgets[WidgetId::' + widget.match_to + '].get()'
327*8975f5c5SAndroid Build Coastguard Worker
328*8975f5c5SAndroid Build Coastguard Worker    return WIDGET_INIT_TEMPLATE.format(
329*8975f5c5SAndroid Build Coastguard Worker        subwidget='description.' if is_graph_description else '',
330*8975f5c5SAndroid Build Coastguard Worker        offset_x=offset_x,
331*8975f5c5SAndroid Build Coastguard Worker        offset_y=offset_y,
332*8975f5c5SAndroid Build Coastguard Worker        width=width,
333*8975f5c5SAndroid Build Coastguard Worker        height=height,
334*8975f5c5SAndroid Build Coastguard Worker        type=widget.type,
335*8975f5c5SAndroid Build Coastguard Worker        font_size=font_size,
336*8975f5c5SAndroid Build Coastguard Worker        coord0=coord0,
337*8975f5c5SAndroid Build Coastguard Worker        coord1=coord1,
338*8975f5c5SAndroid Build Coastguard Worker        coord2=coord2,
339*8975f5c5SAndroid Build Coastguard Worker        coord3=coord3,
340*8975f5c5SAndroid Build Coastguard Worker        color_r=color[0],
341*8975f5c5SAndroid Build Coastguard Worker        color_g=color[1],
342*8975f5c5SAndroid Build Coastguard Worker        color_b=color[2],
343*8975f5c5SAndroid Build Coastguard Worker        color_a=color[3],
344*8975f5c5SAndroid Build Coastguard Worker        match_to=match_to)
345*8975f5c5SAndroid Build Coastguard Worker
346*8975f5c5SAndroid Build Coastguard Worker
347*8975f5c5SAndroid Build Coastguard Workerdef generate_widget_init(widget):
348*8975f5c5SAndroid Build Coastguard Worker    widget_init = '{\n' + widget.type + ' *widget = new ' + widget.constructor + ';\n'
349*8975f5c5SAndroid Build Coastguard Worker
350*8975f5c5SAndroid Build Coastguard Worker    widget_init += generate_widget_init_helper(widget)
351*8975f5c5SAndroid Build Coastguard Worker    widget_init += 'mState.mOverlayWidgets[WidgetId::' + widget.name + '].reset(widget);\n'
352*8975f5c5SAndroid Build Coastguard Worker
353*8975f5c5SAndroid Build Coastguard Worker    if is_graph_type(widget.type):
354*8975f5c5SAndroid Build Coastguard Worker        widget_init += generate_widget_init_helper(widget.description, True)
355*8975f5c5SAndroid Build Coastguard Worker
356*8975f5c5SAndroid Build Coastguard Worker    widget_init += '}\n'
357*8975f5c5SAndroid Build Coastguard Worker
358*8975f5c5SAndroid Build Coastguard Worker    return widget_init
359*8975f5c5SAndroid Build Coastguard Worker
360*8975f5c5SAndroid Build Coastguard Worker
361*8975f5c5SAndroid Build Coastguard Workerdef main():
362*8975f5c5SAndroid Build Coastguard Worker    if len(sys.argv) == 2 and sys.argv[1] == 'inputs':
363*8975f5c5SAndroid Build Coastguard Worker        print(IN_JSON_FILE_NAME)
364*8975f5c5SAndroid Build Coastguard Worker        return
365*8975f5c5SAndroid Build Coastguard Worker    if len(sys.argv) == 2 and sys.argv[1] == 'outputs':
366*8975f5c5SAndroid Build Coastguard Worker        outputs = [
367*8975f5c5SAndroid Build Coastguard Worker            OUT_SOURCE_FILE_NAME,
368*8975f5c5SAndroid Build Coastguard Worker            OUT_HEADER_FILE_NAME,
369*8975f5c5SAndroid Build Coastguard Worker        ]
370*8975f5c5SAndroid Build Coastguard Worker        print(','.join(outputs))
371*8975f5c5SAndroid Build Coastguard Worker        return
372*8975f5c5SAndroid Build Coastguard Worker
373*8975f5c5SAndroid Build Coastguard Worker    with open(IN_JSON_FILE_NAME) as fin:
374*8975f5c5SAndroid Build Coastguard Worker        layout = json.loads(fin.read())
375*8975f5c5SAndroid Build Coastguard Worker
376*8975f5c5SAndroid Build Coastguard Worker    widgets = layout['widgets']
377*8975f5c5SAndroid Build Coastguard Worker
378*8975f5c5SAndroid Build Coastguard Worker    # Read the layouts from the json file and determine alignment of widgets (as they can refer to
379*8975f5c5SAndroid Build Coastguard Worker    # other widgets.
380*8975f5c5SAndroid Build Coastguard Worker    overlay_widgets = {}
381*8975f5c5SAndroid Build Coastguard Worker    for widget_properties in widgets:
382*8975f5c5SAndroid Build Coastguard Worker        widget = OverlayWidget(widget_properties)
383*8975f5c5SAndroid Build Coastguard Worker        overlay_widgets[widget.name] = widget
384*8975f5c5SAndroid Build Coastguard Worker        set_alignment_flags(widget, overlay_widgets)
385*8975f5c5SAndroid Build Coastguard Worker
386*8975f5c5SAndroid Build Coastguard Worker    # Go over the widgets again and generate initialization code.  Note that we need to iterate over
387*8975f5c5SAndroid Build Coastguard Worker    # the widgets in order, so we can't use the overlay_widgets dictionary for iteration.
388*8975f5c5SAndroid Build Coastguard Worker    init_widgets = []
389*8975f5c5SAndroid Build Coastguard Worker    for widget_properties in widgets:
390*8975f5c5SAndroid Build Coastguard Worker        init_widgets.append(generate_widget_init(overlay_widgets[widget_properties['name']]))
391*8975f5c5SAndroid Build Coastguard Worker
392*8975f5c5SAndroid Build Coastguard Worker    with open(OUT_SOURCE_FILE_NAME, 'w') as outfile:
393*8975f5c5SAndroid Build Coastguard Worker        outfile.write(
394*8975f5c5SAndroid Build Coastguard Worker            OUT_SOURCE_FILE_TEMPLATE.format(
395*8975f5c5SAndroid Build Coastguard Worker                script_name=os.path.basename(__file__),
396*8975f5c5SAndroid Build Coastguard Worker                input_file_name=IN_JSON_FILE_NAME,
397*8975f5c5SAndroid Build Coastguard Worker                out_file_name=OUT_SOURCE_FILE_NAME,
398*8975f5c5SAndroid Build Coastguard Worker                init_widgets='\n'.join(init_widgets)))
399*8975f5c5SAndroid Build Coastguard Worker        outfile.close()
400*8975f5c5SAndroid Build Coastguard Worker
401*8975f5c5SAndroid Build Coastguard Worker    with open(OUT_HEADER_FILE_NAME, 'w') as outfile:
402*8975f5c5SAndroid Build Coastguard Worker        widget_ids = [WIDGET_ID_TEMPLATE.format(**widget) for widget in widgets]
403*8975f5c5SAndroid Build Coastguard Worker        widget_x_defs = ["PROC(" + widget['name'] + ")" for widget in widgets]
404*8975f5c5SAndroid Build Coastguard Worker
405*8975f5c5SAndroid Build Coastguard Worker        outfile.write(
406*8975f5c5SAndroid Build Coastguard Worker            OUT_HEADER_FILE_TEMPLATE.format(
407*8975f5c5SAndroid Build Coastguard Worker                script_name=os.path.basename(__file__),
408*8975f5c5SAndroid Build Coastguard Worker                input_file_name=IN_JSON_FILE_NAME,
409*8975f5c5SAndroid Build Coastguard Worker                out_file_name=OUT_SOURCE_FILE_NAME,
410*8975f5c5SAndroid Build Coastguard Worker                widget_ids=''.join(widget_ids),
411*8975f5c5SAndroid Build Coastguard Worker                widget_x_defs=' \\\n'.join(widget_x_defs)))
412*8975f5c5SAndroid Build Coastguard Worker        outfile.close()
413*8975f5c5SAndroid Build Coastguard Worker
414*8975f5c5SAndroid Build Coastguard Worker
415*8975f5c5SAndroid Build Coastguard Workerif __name__ == '__main__':
416*8975f5c5SAndroid Build Coastguard Worker    sys.exit(main())
417