📄 layout.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / 2D rendering module * * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GPAC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */#include "stacks2d.h"#include "grouping.h"#include "visualsurface2d.h"typedef struct{ Fixed width, height, ascent, descent; u32 first_child, nb_children;} LineInfo;typedef struct{ GF_Node *owner; GF_Renderer *compositor; GROUPINGNODESTACK2D Bool start_scroll, is_scrolling; Double start_time, pause_time; GF_List *lines; GF_Rect clip; Fixed last_scroll, prev_rate, scroll_rate, scale_scroll, scroll_len, scroll_min, scroll_max;} LayoutStack;static void layout_reset_lines(LayoutStack *st){ while (gf_list_count(st->lines)) { LineInfo *li = (LineInfo *)gf_list_get(st->lines, 0); gf_list_rem(st->lines, 0); free(li); }}static LineInfo *new_line_info(LayoutStack *st){ LineInfo *li; GF_SAFEALLOC(li, LineInfo); gf_list_add(st->lines, li); return li;}static GFINLINE LineInfo *get_line_info(LayoutStack *st, u32 i){ return (LineInfo *) gf_list_get(st->lines, i);}enum{ L_FIRST, L_BEGIN, L_MIDDLE, L_END,};static u32 get_justify(M_Layout *l, u32 i){ if (l->justify.count <= i) return L_BEGIN; if (!strcmp(l->justify.vals[i], "END")) return L_END; if (!strcmp(l->justify.vals[i], "MIDDLE")) return L_MIDDLE; if (!strcmp(l->justify.vals[i], "FIRST")) return L_FIRST; return L_BEGIN;}static void get_lines_info(LayoutStack *st, M_Layout *l){ u32 i, count; LineInfo *li; Fixed max_w, max_h; max_w = st->clip.width; max_h = st->clip.height; layout_reset_lines(st); count = gf_list_count(st->groups); if (!count) return; li = new_line_info(st); li->first_child = 0; for (i=0; i<count; i++) { ChildGroup2D *cg = (ChildGroup2D *)gf_list_get(st->groups, i); if (!l->horizontal) { /*check if exceed column size or not - if so, move to next column or clip given wrap mode*/ if (cg->final.height + li->height > max_h) { if (l->wrap) { li = new_line_info(st); li->first_child = i; } } if (cg->final.width > li->width) li->width = cg->final.width; li->height += cg->final.height; li->nb_children ++; } else { if (i && (cg->final.width + li->width> max_w)) { if (l->wrap) { if (!li->ascent) { li->ascent = li->height; li->descent = 0; } li = new_line_info(st); li->first_child = i; } } /*get ascent/descent for text or height for non-text*/ if (cg->is_text_group) { if (li->ascent < cg->ascent) li->ascent = cg->ascent; if (li->descent < cg->descent) li->descent = cg->descent; if (li->height < li->ascent + li->descent) li->height = li->ascent + li->descent; } else if (cg->final.height > li->height) { li->height = cg->final.height; } li->width += cg->final.width; li->nb_children ++; } }}static void layout_justify(LayoutStack *st, M_Layout *l){ u32 first, minor, major, i, k, nbLines; Fixed current_top, current_left, h; LineInfo *li; ChildGroup2D *cg, *prev; get_lines_info(st, l); major = get_justify(l, 0); minor = get_justify(l, 1); st->scroll_len = 0; nbLines = gf_list_count(st->lines); if (l->horizontal) { if (l->wrap && !l->topToBottom) { li = (LineInfo*)gf_list_get(st->lines, 0); current_top = st->clip.y - st->clip.height; if (li) current_top += li->height; } else { current_top = st->clip.y; } /*for each line perform adjustment*/ for (k=0; k<nbLines; k++) { li = (LineInfo*)gf_list_get(st->lines, k); first = li->first_child; if (!l->leftToRight) first += li->nb_children - 1; if (!l->topToBottom && k) current_top += li->height; /*set major alignment (X) */ cg = (ChildGroup2D *)gf_list_get(st->groups, first); switch (major) { case L_END: cg->final.x = st->clip.x + st->clip.width - li->width; break; case L_MIDDLE: cg->final.x = st->clip.x + (st->clip.width - li->width)/2; break; case L_FIRST: case L_BEGIN: cg->final.x = st->clip.x; break; } /*for each in the run */ i = first; while (1) { cg = (ChildGroup2D *)gf_list_get(st->groups, i); h = MAX(li->ascent, li->height); switch (minor) { case L_FIRST: cg->final.y = current_top - h; if (cg->is_text_group) { cg->final.y += cg->ascent; } else { cg->final.y += cg->final.height; } break; case L_MIDDLE: cg->final.y = current_top - (h - cg->final.height)/2; break; case L_END: cg->final.y = current_top; break; case L_BEGIN: default: cg->final.y = current_top - h + cg->final.height; break; } /*update left for non-first children in line*/ if (i != first) { if (l->leftToRight) { prev = (ChildGroup2D *)gf_list_get(st->groups, i-1); } else { prev = (ChildGroup2D *)gf_list_get(st->groups, i+1); } cg->final.x = prev->final.x + prev->final.width; } i += l->leftToRight ? +1 : -1; if (l->leftToRight && (i==li->first_child + li->nb_children)) break; else if (!l->leftToRight && (i==li->first_child - 1)) break; } if (l->topToBottom) { current_top -= gf_mulfix(l->spacing, li->height); } else { current_top += gf_mulfix(l->spacing - 1, li->height); } if (l->scrollVertical) { st->scroll_len += li->height; } else { if (st->scroll_len < li->width) st->scroll_len = li->width; } } return; } /*Vertical aligment*/ li = (LineInfo*)gf_list_get(st->lines, 0); if (l->wrap && !l->leftToRight) { current_left = st->clip.x + st->clip.width; if (li) current_left -= li->width; } else { current_left = st->clip.x; switch (minor) { case L_MIDDLE: current_left += (st->clip.width - li->width)/2; break; case L_END: current_left += st->clip.width - li->width; break; case L_BEGIN: case L_FIRST: default: break; } } /*for all columns in run*/ for (k=0; k<nbLines; k++) { li = (LineInfo*)gf_list_get(st->lines, k); first = li->first_child; if (!l->topToBottom) first += li->nb_children - 1; /*set major alignment (Y) */ cg = (ChildGroup2D *)gf_list_get(st->groups, first); switch (major) { case L_END: cg->final.y = st->clip.y - st->clip.height + li->height; break; case L_MIDDLE: cg->final.y = st->clip.y - st->clip.height/2 + li->height/2; break; case L_FIRST: case L_BEGIN: cg->final.y = st->clip.y; break; } /*for each in the run */ i = first; while (1) { cg = (ChildGroup2D *)gf_list_get(st->groups, i); switch (minor) { case L_MIDDLE: cg->final.x = current_left + li->width/2 - cg->final.width/2; break; case L_END: cg->final.x = current_left + li->width - cg->final.width; break; case L_BEGIN: case L_FIRST: default: cg->final.x = current_left; break; } /*update top for non-first children in line*/ if (i != first) { if (l->topToBottom) { prev = (ChildGroup2D *)gf_list_get(st->groups, i-1); } else { prev = (ChildGroup2D *)gf_list_get(st->groups, i+1); } cg->final.y = prev->final.y - prev->final.height; } i += l->topToBottom ? +1 : -1; if (l->topToBottom && (i==li->first_child + li->nb_children)) break; else if (!l->topToBottom && (i==li->first_child - 1)) break; } if (l->leftToRight) { current_left += gf_mulfix(l->spacing, li->width); } else if (k < nbLines - 1) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -