Files
kichikuou_xsystem35-sdl2/src/xcore_maskupdate.c
T
2017-02-11 19:03:05 +09:00

373 lines
10 KiB
C

/*
* xcore_maskupdate.c X11 mask 付き update
*
* Copyright (C) 1997-1998 Masaki Chikama (Wren) <chikama@kasumi.ipl.mech.nagoya-u.ac.jp>
* 1998- <masaki-c@is.aist-nara.ac.jp>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/* $Id: xcore_maskupdate.c,v 1.4 2002/05/02 17:21:32 chikama Exp $ */
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "portab.h"
#include "xcore_private.h"
static Pixmap maskpix; /* clipmask 用 Bitmap */
static Pixmap clippix; /* copy 元 Pixmap */
static Pixmap savepix; /* copy 先 Pixmap */
static Pixmap doublepix;/* double buffer 用 Pixmap */
static GC maskgc; /* clipmask Bitmap 用 GC */
static void draw_5star(double mul, double rad, int off_x, int off_y);
static void draw_6star(double mul, double rad, int off_x, int off_y);
static void draw_windwheel_90(double rad, int r, int off_x, int off_y);
static void draw_windwheel_180(double rad, int r, int off_x, int off_y);
static void draw_windwheel_360(double rad, int r, int off_x, int off_y);
/*
* 五芒星を描く
* mul : 倍率 (1 で 100 * 100) の星が描かれる
* rad : 回転角度(radian)
* off_x: 中心座標の x 方向 offset
* off_y: 中心座標の y 方向 offset
*/
static void draw_5star(double mul, double rad, int off_x, int off_y) {
static XPoint pt[] = {
{ 0, -50},
{-29, 40},
{ 47, -15},
{-47, -15},
{ 29, 40}
};
XPoint p[5];
int i;
/*
* x' cos(X) -sin(X) mul 0 x
* = * *
* y' sin(X) cos(X) 0 mul y
*/
for (i = 0; i < 5; i++) {
p[i].x = mul * (pt[i].x * cos(rad) - pt[i].y * sin(rad)) + off_x;
p[i].y = mul * (pt[i].x * sin(rad) + pt[i].y * cos(rad)) + off_y;
}
XFillPolygon(x11_display, maskpix, maskgc, p, 5, Complex, CoordModeOrigin);
}
/*
* 六芒星を描く
* mul : 倍率 (1 で 100 * 100) の星が描かれる
* rad : 回転角度(radian)
* off_x: 中心座標の x 方向 offset
* off_y: 中心座標の y 方向 offset
*/
static void draw_6star(double mul, double rad, int off_x, int off_y) {
static XPoint pt1[] = {
{ 0, -50},
{-43, 25},
{ 43, 25}
};
static XPoint pt2[] = {
{-43, -25},
{ 0, 50},
{ 43, -25}
};
XPoint p[3];
int i;
for (i = 0; i < 3; i++) {
p[i].x = mul * (pt1[i].x * cos(rad) - pt1[i].y * sin(rad)) + off_x;
p[i].y = mul * (pt1[i].x * sin(rad) + pt1[i].y * cos(rad)) + off_y;
}
XFillPolygon(x11_display, maskpix, maskgc, p, 3, Convex, CoordModeOrigin);
for (i = 0; i < 3; i++) {
p[i].x = mul * (pt2[i].x * cos(rad) - pt2[i].y * sin(rad)) + off_x;
p[i].y = mul * (pt2[i].x * sin(rad) + pt2[i].y * cos(rad)) + off_y;
}
XFillPolygon(x11_display, maskpix, maskgc, p, 3, Convex, CoordModeOrigin);
}
/*
* 扇型の中心角 (てきとー)
* 0.2 radian
*/
#define WHEELDELTA 0.2
/*
* 風車90°
* rad : 回転角 (radian) 0 - pi/2
* r : 半径
* off_x: 中心座標の x 方向 offset
* off_y: 中心座標の y 方向 offset
*/
static void draw_windwheel_90(double rad, int r, int off_x, int off_y) {
XPoint p[3];
p[0].x = 0 + off_x;
p[0].y = 0 + off_y;
p[1].x = r * sin(rad) + off_x;
p[1].y = -r * cos(rad) + off_y;
p[2].x = r * sin(rad + WHEELDELTA) + off_x;
p[2].y = -r * cos(rad + WHEELDELTA) + off_y;
XFillPolygon(x11_display, maskpix, maskgc, p, 3, Convex, CoordModeOrigin);
p[1].x = r * cos(rad) + off_x;
p[1].y = r * sin(rad) + off_y;
p[2].x = r * cos(rad + WHEELDELTA) + off_x;
p[2].y = r * sin(rad + WHEELDELTA) + off_y;
XFillPolygon(x11_display, maskpix, maskgc, p, 3, Convex, CoordModeOrigin);
p[1].x = -r * sin(rad) + off_x;
p[1].y = r * cos(rad) + off_y;
p[2].x = -r * sin(rad + WHEELDELTA) + off_x;
p[2].y = r * cos(rad + WHEELDELTA) + off_y;
XFillPolygon(x11_display, maskpix, maskgc, p, 3, Convex, CoordModeOrigin);
p[1].x = -r * cos(rad) + off_x;
p[1].y = -r * sin(rad) + off_y;
p[2].x = -r * cos(rad + WHEELDELTA) + off_x;
p[2].y = -r * sin(rad + WHEELDELTA) + off_y;
XFillPolygon(x11_display, maskpix, maskgc, p, 3, Convex, CoordModeOrigin);
}
/*
* 風車180°
* rad : 回転角 (radian) 0 - pi
* r : 半径
* off_x: 中心座標の x 方向 offset
* off_y: 中心座標の y 方向 offset
*/
static void draw_windwheel_180(double rad, int r, int off_x, int off_y) {
XPoint p[3];
p[0].x = 0 + off_x;
p[0].y = 0 + off_y;
p[1].x = -r * cos(rad) + off_x;
p[1].y = -r * sin(rad) + off_y;
p[2].x = -r * cos(rad + WHEELDELTA) + off_x;
p[2].y = -r * sin(rad + WHEELDELTA) + off_y;
XFillPolygon(x11_display, maskpix, maskgc, p, 3, Convex, CoordModeOrigin);
p[1].x = r * cos(rad) + off_x;
p[1].y = r * sin(rad) + off_y;
p[2].x = r * cos(rad + WHEELDELTA) + off_x;
p[2].y = r * sin(rad + WHEELDELTA) + off_y;
XFillPolygon(x11_display, maskpix, maskgc, p, 3, Convex, CoordModeOrigin);
}
/*
* 風車180°
* rad : 回転角 (radian) 0 - 2pi
* r : 半径
* off_x: 中心座標の x 方向 offset
* off_y: 中心座標の y 方向 offset
*/
static void draw_windwheel_360(double rad, int r, int off_x, int off_y) {
XPoint p[3];
p[0].x = 0 + off_x;
p[0].y = 0 + off_y;
p[1].x = -r * cos(rad) + off_x;
p[1].y = -r * sin(rad) + off_y;
p[2].x = -r * cos(rad + WHEELDELTA) + off_x;
p[2].y = -r * sin(rad + WHEELDELTA) + off_y;
XFillPolygon(x11_display, maskpix, maskgc, p, 3, Convex, CoordModeOrigin);
}
/*
* マスク付き領域更新
* sx: コピー元 x 座標
* sy: コピー元 y 座標
* w : コピー元 width
* h : コピー元 height
* dx: コピー先 x 座標
* dy: コピー先 y 座標
* func: マスク種類
* 44: 五芒星(内->外)
* 45: 五芒星(外->内)
* 46: 六芒星(内->外)
* 47: 六芒星(外->内)
* 50: 風車90°
* 51: 風車180°
* 52: 風車360°
* step: 呼び出し番号 0 - 256
*/
void Xcore_maskupdate(int sx, int sy, int w, int h, int dx, int dy, int func, int step) {
GC gc;
dx -= view_x;
dy -= view_y;
if (step == 0) {
/* 最初にいろいろと準備 */
XSync(x11_display, False);
/* コピー元を DIB から pixmap に持って来る */
clippix = x11_clip_from_DIB(sx, sy, w, h);
/* clip mask 用 Pixmap の生成 */
maskpix = XCreatePixmap(x11_display, x11_window, w, h, 1);
maskgc = XCreateGC(x11_display, maskpix, None, NULL);
/* clipmask 用 Pixmap の初期化 */
XSetForeground(x11_display, maskgc, 0);
XFillRectangle(x11_display, maskpix, maskgc, 0, 0, w, h);
/* 線が交差するときの塗りつぶしのルールを設定 */
XSetFillRule(x11_display, maskgc, WindingRule);
/* 更新先の Window の領域を保存 */
savepix = XCreatePixmap(x11_display, x11_window, w, h, WIN_DEPTH);
XCopyArea(x11_display, x11_window, savepix, x11_gc_pix,
winoffset_x + dx, winoffset_y + dy, w, h, 0, 0);
/* ダブルバッファ用に Pixmap を確保 */
doublepix = XCreatePixmap(x11_display, x11_window, w, h, WIN_DEPTH);
XCopyArea(x11_display, x11_window, doublepix, x11_gc_pix,
winoffset_x + dx, winoffset_y + dy, w, h, 0, 0);
XSync(x11_display, False);
return;
} else if (step == 256) {
/* 最後に後始末 */
#if 0
XCopyArea(x11_display, clippix, x11_window, x11_gc_pix,
0, 0, w, h, winoffset_x + dx, winoffset_y + dy);
#endif
#if 0
XCopyArea(x11_display, clippix, x11_pixmap, x11_gc_pix,
0, 0, w, h, winoffset_x + dx, winoffset_y + dy);
ags_updateFull();
#endif
ags_copyArea(sx, sy, w, h, dx + view_x, dy + view_y);
ags_updateArea(dx + view_x, dy + view_y, w, h);
XFreePixmap(x11_display, maskpix);
XFreePixmap(x11_display, clippix);
XFreePixmap(x11_display, savepix);
XFreePixmap(x11_display, doublepix);
XFreeGC(x11_display, maskgc);
return;
}
/* clipmask 用の GC を生成 (毎回生成しなくても良いかも?) */
gc = XCreateGC(x11_display, clippix, None, NULL);
XSetClipMask(x11_display, gc, maskpix);
XSetClipOrigin(x11_display, gc, 0, 0);
switch(func) {
case 44:
case 46:
/* 内から外へ */
XSetForeground(x11_display, maskgc, 0);
XFillRectangle(x11_display, maskpix, maskgc, 0, 0, w, h);
XSetForeground(x11_display, maskgc, 1);
break;
case 45:
case 47:
/* 外から内へ */
XSetForeground(x11_display, maskgc, 1);
XFillRectangle(x11_display, maskpix, maskgc, 0, 0, w, h);
XSetForeground(x11_display, maskgc, 0);
break;
default:
XSetForeground(x11_display, maskgc, 1);
}
/* mask を描画 */
switch(func) {
case 44:
draw_5star(1.5 * (max(w,h) * step) / (256 * 50.0),
1.0 * M_PI * step / 256, w/2, h/2);
break;
case 45:
draw_5star(1.5 * (max(w,h) * (256-step)) / (256 * 50.0),
1.0 * M_PI * step / 256, w/2, h/2);
break;
case 46:
draw_6star((max(w,h) * step) / (256 * 50.0),
1.0 * M_PI * step / 256, w/2, h/2);
break;
case 47:
draw_6star((max(w,h) * (256-step)) / (256 * 50.0),
1.0 * M_PI * step / 256, w/2, h/2);
break;
case 50:
draw_windwheel_90(0.5 * M_PI * step / 256, sqrt(w*w+h*h)/2,
w/2, h/2);
break;
case 51:
draw_windwheel_180(1.0 * M_PI * step / 256, sqrt(w*w+h*h)/2,
w/2, h/2);
break;
case 52:
draw_windwheel_360(2.0 * M_PI * step / 256, sqrt(w*w+h*h)/2,
w/2, h/2);
break;
}
/* double buffer へ 保存した window の内容をコピー */
XCopyArea(x11_display, savepix, doublepix, x11_gc_win,
0, 0, w, h, 0, 0);
/* コピー元の内容を mask付きで double buffer へコピー */
XCopyArea(x11_display, clippix, doublepix, gc,
0, 0, w, h, 0, 0);
/* double buffer から window へコピー */
XCopyArea(x11_display, doublepix, x11_window, x11_gc_win,
0, 0, w, h, winoffset_x + dx, winoffset_y + dy);
/* 同期 */
XSync(x11_display, False);
/* clipmask 用 gc の破棄 */
XFreeGC(x11_display, gc);
}