DSCREEN.C

[目次 | 関数]

目次

関数一覧


   1|/***************************************************************************
   2|*  1. <<< ダブルバッファ・ワーク画面 [DScreen] >>> 
   3|*
   4|*・透明色を扱うことが出来るように、バッファを 2画面分用意したワーク画面。
   5|*・DrawScr インターフェイスに対応しています。
   6|*・裏画面を持ついわゆるダブルバッファは、Screen_Sw クラスを参照。
   7|*
   8|* 2. <<<【属性】>>>
   9|*・先頭アドレス [DScreen.adr, DScreen_getAdr()]
  10|*・1画面分のバッファ・サイズ(byte) [DScreen_getSingleSize()]
  11|*・ワーク画面のサイズ [DScreen.width, DScreen_getWidth(), DScreen.height,
  12|*                      DScreen_getHeight()]
  13|*・オフセット [DScreen.offsetX, DScreen_getOffsetX(), DScreen.offsetY,
  14|*              DScreen_getOffsetY(), DScreen_setOffset()]
  15|*・クリップ領域 [DScreen_getClipMinX(), DScreen_getClipMaxX(),
  16|*                DScreen_getClipMinY(), DScreen_getClipMaxY()]
  17|*・1バイトあたりのピクセル数 [DScreen_getPixelPerByte()]
  18|*・1ピクセルあたりのビット数 [DScreen_getBitPerPixel()]
  19|*
  20|* 3. <<< 用語 [オフセット] >>>
  21|* pset() の座標をずらす度合い
  22|***************************************************************************/
  23|
  24|#include "mixer_precomp.h"
  25|// #pragma hdrstop ("mixer_precomp")
  26|
  27|#ifdef  USES_MXP_AUTOINC
  28| #include  <DScreen.ah>  /* Auto include header, Look at mixer-... folder */
  29|#endif
  30|
  31|/***************************************************************************
  32|*  4. <<< 初期化する [DScreen_init()] >>>
  33|*【補足】
  34|*・adr が指しているバッファは、DScreen_clear 関数で明示的に初期化する
  35|*  必要があります。
  36|****************************************************************************/
  37|void  DScreen_init( DScreen* m, char* adr, int width, int height )
  38|{
  39|  m->adr = adr;
  40|  m->width = width;   m->height = height;
  41|  m->offsetX = 0;      m->offsetY = 0;
  42|  m->clipX = 0;         m->clipY = 0;
  43|  m->clipWidth = width;  m->clipHeight = height;
  44|}
  45|
  46|
  47|/***************************************************************************
  48|* 5. <<< 画面全体を指定の色 color でクリアする [DScreen_clear()] >>>
  49|****************************************************************************/
  50|void  DScreen_clear( DScreen* m, int color )
  51|{
  52|  int  i;
  53|  int*  p = (int*)DScreen_getAdr(m);
  54|
  55|  color = (color << 4 ) | color;
  56|  color = (color << 24) | (color << 16) | (color << 8) | color ;
  57|
  58|  for ( i = 0; i < DScreen_getWidth(m) * DScreen_getHeight(m)
  59|                   * 2 / DScreen_getPixelPerByte(m) / (int)sizeof(int);
  60|          i++ ) {
  61|    *p = color;  p++;
  62|  }
  63|}
  64|
  65|
  66|/***************************************************************************
  67|*  6. <<< 画面全体を透明色でクリアする [DScreen_trueClear()] >>>
  68|****************************************************************************/
  69|void  DScreen_trueClear( DScreen* m )
  70|{
  71|  int  i;
  72|  int*  p = (int*)DScreen_getAdr(m);
  73|
  74|  for ( i = 0; i < DScreen_getWidth(m) * DScreen_getHeight(m)
  75|                   / DScreen_getPixelPerByte(m) / (int)sizeof(int);
  76|          i++ ) {
  77|    *p = 0;  p++;
  78|  }
  79|  for ( i = 0; i < DScreen_getWidth(m) * DScreen_getHeight(m)
  80|                   / DScreen_getPixelPerByte(m) / (int)sizeof(int);
  81|          i++ ) {
  82|    *p = -1;  p++;
  83|  }
  84|}
  85|
  86|
  87|/***************************************************************************
  88|*  7. <<< クリッピング領域を設定する [DScreen_setClip()] >>>
  89|****************************************************************************/
  90|void  DScreen_setClip( DScreen* m, int x, int y, int w, int h )
  91|{
  92|  m->clipX = x;      m->clipY = y;
  93|  m->clipWidth = w;  m->clipHeight = h;
  94|}
  95|
  96|
  97|/***************************************************************************
  98|*  8. <<< クリッピング領域の設定を解除する [DScreen_clearClip()] >>>
  99|****************************************************************************/
 100|void  DScreen_clearClip( DScreen* m )
 101|{
 102|  m->clipX = 0;                m->clipY = 0;
 103|  m->clipWidth = m->width;  m->clipHeight = m->height;
 104|}
 105|
 106|
 107|#ifdef  USES_TYPEX
 108|
 109|/***************************************************************************
 110|*  9. <<< 透明色で矩形を塗りつぶす [DScreen_rectFillClear2()] >>>
 111|****************************************************************************/
 112|void  DScreen_rectFillClear2( DScreen* m, int x1, int y1, int x2, int y2 )
 113|{
 114|  int     y;
 115|  UINT32*  p =  (UINT32*)DScreen_pgetAdr( m, x1, y1 );
 116|  UINT32*  p2 = (UINT32*)DScreen_pgetSubAdr( m, x1, y1 );
 117|  UINT32* overP;
 118|
 119|  const int  nPixelInUINT32 = /* UINT32 型変数の1回の代入でコピーされるピクセル数 */
 120|    sizeof(UINT32)*8 / DScreen_getBitPerPixel(m);
 121|  const int  width = x2 - x1 + 1;
 122|
 123|  const int  countX = /* 1行あたりの UINT32 の代入回数 */
 124|    width / nPixelInUINT32;
 125|  const int  add =  /* 次の行の p の増分 */
 126|    ( DScreen_getWidth( m ) - width ) / nPixelInUINT32;
 127|
 128|  #ifdef _CHECKER
 129|    if ( x1 < 0 || x1 > DScreen_getWidth( m ) )  error();
 130|    if ( x2 < 0 || x2 > DScreen_getWidth( m ) )  error();
 131|    if ( x1 > x2 )  error();
 132|    if ( y1 < 0 || y1 > DScreen_getHeight( m ) )  error();
 133|    if ( y2 < 0 || y2 > DScreen_getHeight( m ) )  error();
 134|    if ( y1 > y2 )  error();
 135|    /* 塗りつぶす範囲は、UINT32 のアラインに合わせること */
 136|    if ( x1 % nPixelInUINT32 != 0 )  error();
 137|    if ( x2 % nPixelInUINT32 != nPixelInUINT32 -1 )  error();
 138|  #endif
 139|
 140|  for ( y = y1; y <= y2; y++ ) {
 141|    overP = p + countX;
 142|    for ( ; p < overP; p++, p2++ ) {
 143|      *p = 0;  *p2 = 0xFFFFFFFF;
 144|    }
 145|    p += add;  p2 += add;
 146|  }
 147|}
 148|
 149|#endif /* USES_TYPEX */
 150|
 151|
 152|/***************************************************************************
 153|*  10. <<< (x,y) の位置に点を打つ [DScreen_pset()] >>>
 154|*  クリッピング処理、オフセットあり
 155|*  領域外の場合は点を描かない
 156|****************************************************************************/
 157|void  DScreen_pset( DScreen* m, int x, int y, int color )
 158|{
 159|  char*  p;
 160|
 161|  /* オフセット */
 162|  x += DScreen_getOffsetX(m);
 163|  y += DScreen_getOffsetY(m);
 164|
 165|  /* クリッピング */
 166|  if ( x < DScreen_getClipMinX(m) ||
 167|       x > DScreen_getClipMaxX(m) ||
 168|       y < DScreen_getClipMinY(m) ||
 169|       y > DScreen_getClipMaxY(m) )
 170|    return;
 171|
 172|  /* アドレス */
 173|  p = DScreen_getAdr(m) +
 174|       ( DScreen_getWidth(m) * y + x )
 175|       / DScreen_getPixelPerByte(m);
 176|
 177|  #if DScreen_getPixelPerByte(m) != 2
 178|  #error
 179|  #endif
 180|
 181|  color = (color & 0x0F);
 182|
 183|  if ( (x & 1) == 0 ) {
 184|    *p = (*p & 0xF0) | color;
 185|    p += DScreen_getSingleSize(m);
 186|    *p = (*p & 0xF0);
 187|  }
 188|  else {
 189|    *p = (*p & 0x0F) | (color << 4);
 190|    p += DScreen_getSingleSize(m);
 191|    *p = (*p & 0x0F);
 192|  }
 193|}
 194|
 195|
 196|/***************************************************************************
 197|*  11. <<< XOR 演算して点を描く [DScreen_psetXor()] >>>
 198|*  クリッピング処理、オフセットあり
 199|*  x が領域外の場合は点を描かない
 200|*  y が領域外の場合はその領域の境界に描く
 201|*  ・x, y : 位置
 202|*  ・color
 203|****************************************************************************/
 204|void  DScreen_psetXor( DScreen* m, int x, int y, int color )
 205|{
 206|  char*  p;
 207|
 208|  /* オフセット */
 209|  x += DScreen_getOffsetX(m);
 210|  y += DScreen_getOffsetY(m);
 211|
 212|  /* クリッピング */
 213|  if ( x < DScreen_getClipMinX(m) ||
 214|       x > DScreen_getClipMaxX(m) )  return;
 215|
 216|  if ( y < DScreen_getClipMinY(m) )
 217|    y = DScreen_getClipMinY(m);
 218|  if ( y > DScreen_getClipMaxY(m) )
 219|    y = DScreen_getClipMaxY(m);
 220|
 221|  /* アドレス */
 222|  p = DScreen_getAdr(m) +
 223|       ( DScreen_getWidth(m) * y + x )
 224|       / DScreen_getPixelPerByte(m);
 225|
 226|  #if DScreen_getPixelPerByte(m) != 2
 227|  #error
 228|  #endif
 229|
 230|  color = (color & 0x0F);
 231|
 232|  if ( (x & 1) == 0 ) {
 233|    *p = *p ^ color;
 234|    p += DScreen_getSingleSize(m);
 235|    *p = *p ^ color;
 236|  }
 237|  else {
 238|    *p = *p ^ ( color << 4 );
 239|    p += DScreen_getSingleSize(m);
 240|    *p = *p ^ ( color << 4 );
 241|  }
 242|}
 243|
 244|
 245|#ifdef USES_TYPEX
 246|#ifdef USES_MASK
 247|
 248|/**************************************************************************
 249|*  12. <<< 数ピクセル描画する [DScreen_psets()] >>>
 250|*【引数】
 251|*  ・unsigned char*  pattern;  ピクセル・パターンが格納されているアドレス
 252|*  ・int  nPixel;              ピクセル数
 253|*【機能】
 254|*・x,y から水平右方向に、数ピクセルのピクセル・パターンを描画します。
 255|*【補足】
 256|*・UNIT32 代入を用いて高速に処理します。
 257|*・ピクセル・パターンは、下位ビット→上位ビットが左→右のピクセルに対応
 258|*  します。ピクセル・パターンは、1bpp です。
 259|*・ピクセル・パターン中のビットが0の位置に相当するピクセルの色は、
 260|*  変化しません。透明色に相当します。
 261|*・たとえば、文字を描くときに使うことができます。
 262|*・4bpp 専用です。
 263|***************************************************************************/
 264|void  DScreen_psets( DScreen* m, int x, int y, unsigned char* pattern,
 265|  int nPixel, int color )
 266|{
 267|  UINT32*  p = (UINT32*)DScreen_pgetAdr( m, x, y );
 268|  UINT32*  p2 = (UINT32*)DScreen_pgetSubAdr( m, x, y );
 269|  UINT32   inMask, outMask, overMask;
 270|  unsigned char*  pattern_over;
 271|  #ifdef _32BIT
 272|    int  sft = (x & 0x07) << 2;  /* シフト数、x/2 の余り×4 (32bitの余り) */
 273|  #endif
 274|  #ifdef _16BIT
 275|    int  sft = (x & 0x01) << 2;  /* シフト数、x/2 の余り×4 (8bitの余り) */
 276|  #endif
 277|
 278|  #ifdef _CHECKER
 279|    if ( nPixel % 8 != 0 || nPixel < 8 )  error();
 280|    if ( DScreen_getBitPerPixel(m) != 4 )  error();
 281|    if ( x < 0 || x + nPixel > m->width )  error();
 282|    if ( y < 0 || y >= m->height )  error();
 283|  #endif
 284|
 285|  overMask = 0;
 286|
 287|  /* (nPixel/8) 回だけ 32bit コピーする */
 288|  pattern_over = pattern + (nPixel/8);
 289|  for ( pattern ; pattern < pattern_over; pattern ++ ) {
 290|
 291|    inMask = Mask_bpp1to4[*pattern];
 292|    outMask = (inMask << sft) | overMask;  /* 左シフトでピクセルは右へ */
 293|    *p = ( ( Mask_colors16[color] & outMask ) | ( ~outMask & *p ) );
 294|    *p2 = ( ~outMask & *p2 );
 295|
 296|    overMask = V800X_shr( inMask, 32-sft );
 297|    p++;  p2++;
 298|  }
 299|
 300|  /* あふれた分の 32bit コピーをする */
 301|  *p = ( ( Mask_colors16[color] & overMask ) | ( ~overMask & *p ) );
 302|  *p2 = ( ~overMask & *p2 );
 303|}
 304|
 305|#endif /* USES_MASK */
 306|#endif /* USES_TYPEX */
 307|
 308|
 309|/***************************************************************************
 310|*  13. <<< 塗りつぶす(XOR アルゴリズム)[DScreen_xorPaint()] >>>
 311|*  塗りつぶす領域は、Draw_lineForXorPaint で指定してあること。
 312|*  境界線は無くなることもあるので、別に境界線を描画すること。
 313|****************************************************************************/
 314|void  DScreen_xorPaint( DScreen* m )
 315|{
 316|  char*  p = DScreen_getAdr(m);
 317|  char*  p2 = p + DScreen_getWidth(m)  /* p より1段下 */
 318|                  / DScreen_getPixelPerByte(m);
 319|  char*  overP = p + DScreen_getSingleSize(m);
 320|  char*  overP2 = overP + DScreen_getSingleSize(m);
 321|
 322|  for ( ; p < overP;  p++, p2++ ) {
 323|    *p2 = *p ^ *p2;
 324|  }
 325|  for ( ; p < overP2;  p++, p2++ ) {
 326|    *p2 = ~(*p ^ *p2);  /* NOT XOR */
 327|  }
 328|}
 329|
 330|
 331|#ifdef USES_DRAWSCR
 332|
 333|/***************************************************************************
 334|*  14. <<< 画面全体を target 画面へコピーする(同期を取る)[DScreen_flushTo2()] >>>
 335|*  ・target : コピー先画面
 336|*  ・baseX, baseY : target 基点画面位置、ただし x は 8 の倍数
 337|*  透明色は #define DScreen_ClearColor による
 338|****************************************************************************/
 339|void  DScreen_flushTo2( DScreen* m, DrawScr target,
 340|  Mask_A* mask, int baseX, int baseY )
 341|{
 342|  DrawScr_flushFromDScreen2( target, m, mask, baseX, baseY  );
 343|}
 344|
 345|#endif /* USES_DRAWSCR */
 346|
 347|#ifdef  _STDLIB
 348|
 349|/***************************************************************************
 350|*  15. <<< デバッグ表示 [DScreen_print()] >>>
 351|****************************************************************************/
 352|void  DScreen_print( DScreen* m, FILE* file )
 353|{
 354|  int  x,y;
 355|  unsigned char  c;
 356|
 357|  #ifdef _CHECKER
 358|  if ( DScreen_getPixelPerByte(m) != 2 )  error();
 359|  #endif
 360|
 361|  fprintf( file, "[DScreen] adr=%p, width=%d, height=%d, offX=%d, offY=%d",
 362|     m->adr, m->width, m->height, m->offsetX, m->offsetY );
 363|
 364|  for ( y = 0; y < m->height*2; y++ ) {
 365|    for ( x = 0; x < m->width; x+=2 ) {
 366|      if ( x == 0 )  fprintf( file, "\n " );
 367|      c = m->adr[(y * m->width + x) / DScreen_getPixelPerByte(m)];
 368|      fprintf( file, "%01X", c & 0x0F );
 369|      fprintf( file, "%01X", c >> 4 );
 370|    }
 371|  }
 372|  fprintf( file, "\n " );
 373|}
 374|
 375|#endif  /* _STDLIB */
 376|
 377|
 378|#ifdef USES_DRAWSCR
 379|
 380|/***************************************************************************
 381|*  16. <<< DrawScr インターフェイスを返す [DScreen_inf_DrawScr()] >>>
 382|****************************************************************************/
 383|
 384|int  DScreen_getWidthF( DScreen* m )
 385|  { return DScreen_getWidth( m ); }
 386|int  DScreen_getHeightF( DScreen* m )
 387|  { return DScreen_getHeight( m ); }
 388|
 389|/* 具象クラスの関数定義 */
 390|INF_SUB_FUNC( DScreen, DrawScr, DScreen_by_DrawScr )
 391|
 392|/* インターフェイス取得関数の定義(INF_SUB_FUNC より後に書くこと) */
 393|DrawScr  DScreen_inf_DrawScr( DScreen* m )
 394|{
 395|  INF_SUB_SC_START( DScreen, DrawScr );
 396|  INF_SUB_SC_METHOD_0( DScreen,getWidth, int, DScreen_getWidthF, DrawScr )
 397|  INF_SUB_SC_METHOD_0( DScreen,getHeight, int, DScreen_getHeightF, DrawScr )
 398|  INF_SUB_SC_METHOD_NULL( DScreen,getExAdr )
 399|  INF_SUB_SC_METHOD_NULL( DScreen,getExVectors )
 400|  INF_SUB_SC_METHOD_1( DScreen,clear, void, DScreen_clear, DrawScr,int )
 401|  INF_SUB_SC_METHOD_3( DScreen,pset, void, DScreen_pset, DrawScr,int,int,int )
 402|  INF_SUB_SC_METHOD_NULL( DScreen,exPset )
 403|  INF_SUB_SC_METHOD_3( DScreen,psetXor, void, DScreen_psetXor, DrawScr,int,int,int )
 404|  #ifdef USES_MASK
 405|    INF_SUB_SC_METHOD_5( DScreen,psets, void, DScreen_psets, DrawScr,int,int,unsigned char*,int,int )
 406|  #endif
 407|  INF_SUB_SC_METHOD_0( DScreen,xorPaint, void, DScreen_xorPaint, DrawScr )
 408|  #ifdef USES_MASK
 409|    INF_SUB_SC_METHOD_4( DScreen,flushTo2, void, DScreen_flushTo2, DrawScr,DrawScr,Mask_A*,int,int )
 410|  #ifdef USES_SCREEN
 411|    INF_SUB_SC_METHOD_NULL( DScreen,flushFromScreen2 )
 412|  #endif
 413|  INF_SUB_SC_METHOD_NULL( DScreen,flushFromDScreen2 )
 414|  #endif /* USES_MASK */
 415|  INF_SUB_SC_END( DScreen, DrawScr );
 416|}
 417|
 418|
 419|#endif  /* USES_DRAWSCR */
 420| 
 421|