summary refs log tree commit diff
diff options
context:
space:
mode:
authorIrene Knapp <ireneista@gmail.com>2020-05-19 21:44:18 -0700
committerIrene Knapp <ireneista@gmail.com>2020-05-19 21:44:18 -0700
commit3b9d3955fe61ebd6cdb1249d2a206d7dd4c237eb (patch)
treeb099eb1fb3699cb33b2fbc96d51e09f4e51ea3c0
parent7aa23967a3fc2cc63c85d2108cc527d2a0a4fd88 (diff)
Yay! Big kitty!
-rw-r--r--src/oneko.c119
1 files changed, 97 insertions, 22 deletions
diff --git a/src/oneko.c b/src/oneko.c
index d2b81fe..ab4208b 100644
--- a/src/oneko.c
+++ b/src/oneko.c
@@ -68,6 +68,7 @@ char	*Foreground = NULL;		/*   foreground	*/
 char	*Background = NULL;		/*   background	*/
 long	IntervalTime = 0L;		/*   time	*/
 double	NekoSpeed = (double)0;		/*   speed	*/
+int ScaleFactor = NOTDEFINED;
 int	IdleSpace = 0;			/*   idle	*/
 int	NekoMoyou = NOTDEFINED;		/*   tora	*/
 int	NoShape = NOTDEFINED;		/*   noshape	*/
@@ -269,6 +270,52 @@ Animation	AnimationPattern[][2] =
 static void NullFunction();
 
 /*
+ *	Scales the bitmap.
+ */
+
+char*
+ScaleBitmap(char* inputBitmap)
+{
+    int scaledBitmapWidth = BITMAP_WIDTH * ScaleFactor;
+    int scaledBitmapHeight = BITMAP_HEIGHT * ScaleFactor;
+    int scaledBitmapSize = (scaledBitmapWidth / 8) * scaledBitmapHeight;
+    char* result = malloc(scaledBitmapSize);
+
+    for (int i = 0; i < scaledBitmapSize; i++) {
+      result[i] = 0x00;
+    }
+
+    for (int srcY = 0; srcY < BITMAP_HEIGHT; srcY++) {
+      for (int srcX = 0; srcX < BITMAP_WIDTH; srcX++) {
+        int srcByteOffset = (srcX / 8) + (srcY * BITMAP_WIDTH / 8);
+        int srcBitOffset = (srcX % 8);
+        char bit = inputBitmap[srcByteOffset] >> srcBitOffset & 0x01;
+
+        if (bit != 0) {
+          for (int ySub = 0; ySub < ScaleFactor; ySub++) {
+            int dstY = srcY * ScaleFactor + ySub;
+
+            for (int xSub = 0; xSub < ScaleFactor; xSub += 8) {
+              int dstX = srcX * ScaleFactor + xSub;
+              int dstByteOffset = (dstX / 8) + (dstY * scaledBitmapWidth / 8);
+              int dstBitCount = ScaleFactor - xSub;
+              if (dstBitCount > 8) {
+                dstBitCount = 8;
+              }
+              int dstBitOffset = (dstX % 8);
+              char dstBitMask = ((1 << dstBitCount) - 1) << dstBitOffset;
+
+              result[dstByteOffset] |= dstBitMask;
+            }
+          }
+        }
+      }
+    }
+
+    return result;
+}
+
+/*
  *	$@%S%C%H%^%C%W%G!<%?!&(JGC $@=i4|2=(J
  */
 
@@ -289,20 +336,28 @@ InitBitmapAndGCs()
 	 BitmapGCDataTablePtr->GCCreatePtr != NULL;
 	 BitmapGCDataTablePtr++) {
 
+        char* scaledPixelPattern = ScaleBitmap(BitmapGCDataTablePtr->PixelPattern[NekoMoyou]);
+
 	*(BitmapGCDataTablePtr->BitmapCreatePtr)
 	    = XCreatePixmapFromBitmapData(theDisplay, theRoot,
-		BitmapGCDataTablePtr->PixelPattern[NekoMoyou],
-		BITMAP_WIDTH, BITMAP_HEIGHT,
+		scaledPixelPattern,
+		BITMAP_WIDTH * ScaleFactor, BITMAP_HEIGHT * ScaleFactor,
 		theForegroundColor.pixel,
 		theBackgroundColor.pixel,
 		DefaultDepth(theDisplay, theScreen));
 
+        free(scaledPixelPattern);
+
 	theGCValues.tile = *(BitmapGCDataTablePtr->BitmapCreatePtr);
 
+        char* scaledMaskPattern = ScaleBitmap(BitmapGCDataTablePtr->MaskPattern[NekoMoyou]);
+
 	*(BitmapGCDataTablePtr->BitmapMasksPtr)
 	    = XCreateBitmapFromData(theDisplay, theRoot,
-		BitmapGCDataTablePtr->MaskPattern[NekoMoyou],
-		BITMAP_WIDTH, BITMAP_HEIGHT);
+		scaledMaskPattern,
+		BITMAP_WIDTH * ScaleFactor, BITMAP_HEIGHT * ScaleFactor);
+
+        free(scaledMaskPattern);
 
 	*(BitmapGCDataTablePtr->GCCreatePtr)
 	    = XCreateGC(theDisplay, theWindow,
@@ -368,6 +423,14 @@ GetResources()
     }
   }
 
+  if (ScaleFactor == NOTDEFINED) {
+    if ((resource = NekoGetDefault("scale")) != NULL) {
+      if (num = atoi(resource)) {
+	ScaleFactor = num;
+      }
+    }
+  }
+
   if (IdleSpace == 0) {
     if ((resource = NekoGetDefault("idle")) != NULL) {
       if (num = atoi(resource)) {
@@ -408,6 +471,9 @@ GetResources()
   if (IntervalTime == 0) {
     IntervalTime = AnimalDefaultsDataTable[NekoMoyou].time;
   }
+  if (ScaleFactor == NOTDEFINED) {
+    ScaleFactor = 1;
+  }
   if (NekoSpeed == (double)0) {
     NekoSpeed = (double)(AnimalDefaultsDataTable[NekoMoyou].speed);
   }
@@ -690,7 +756,7 @@ InitScreen(DisplayName)
       CWOverrideRedirect;
 
   theWindow = XCreateWindow(theDisplay, theRoot, 0, 0,
-			    BITMAP_WIDTH, BITMAP_HEIGHT,
+			    BITMAP_WIDTH * ScaleFactor, BITMAP_HEIGHT * ScaleFactor,
 			    0, theDepth, InputOutput, CopyFromParent,
 			    theWindowMask, &theWindowAttributes);
 
@@ -815,7 +881,7 @@ DrawNeko(x, y, DrawAnime)
 	DontMapped = 0;
       }
       XFillRectangle(theDisplay, theWindow, DrawGC,
-		     0, 0, BITMAP_WIDTH, BITMAP_HEIGHT);
+		     0, 0, BITMAP_WIDTH * ScaleFactor, BITMAP_HEIGHT * ScaleFactor);
     }
 
     XFlush(theDisplay);
@@ -835,7 +901,7 @@ void
 RedrawNeko()
 {
   XFillRectangle(theDisplay, theWindow, NekoLastGC,
-		 0, 0, BITMAP_WIDTH, BITMAP_HEIGHT);
+		 0, 0, BITMAP_WIDTH * ScaleFactor, BITMAP_HEIGHT * ScaleFactor);
 
   XFlush(theDisplay);
 }
@@ -915,15 +981,15 @@ IsWindowOver()
     if (NekoY <= 0) {
 	NekoY = 0;
 	ReturnValue = True;
-    } else if (NekoY >= WindowHeight - BITMAP_HEIGHT) {
-	NekoY = WindowHeight - BITMAP_HEIGHT;
+    } else if (NekoY >= WindowHeight - BITMAP_HEIGHT * ScaleFactor) {
+	NekoY = WindowHeight - BITMAP_HEIGHT * ScaleFactor;
 	ReturnValue = True;
     }
     if (NekoX <= 0) {
 	NekoX = 0;
 	ReturnValue = True;
-    } else if (NekoX >= WindowWidth - BITMAP_WIDTH) {
-	NekoX = WindowWidth - BITMAP_WIDTH;
+    } else if (NekoX >= WindowWidth - BITMAP_WIDTH * ScaleFactor) {
+	NekoX = WindowWidth - BITMAP_WIDTH * ScaleFactor;
 	ReturnValue = True;
     }
 
@@ -1048,24 +1114,24 @@ CalcDxDy()
 	    LargeX = (double)(MouseX - NekoX - BITMAP_WIDTH / 2);
 
 	  LargeY = (double)(theTargetAttributes.y
-			    + YOffset - NekoY - BITMAP_HEIGHT);
+			    + YOffset - NekoY - BITMAP_HEIGHT * ScaleFactor);
 	}
 	else {
 	  MouseX = theTargetAttributes.x 
 	    + theTargetAttributes.width / 2 + XOffset;
 	  MouseY = theTargetAttributes.y + YOffset;
-	  LargeX = (double)(MouseX - NekoX - BITMAP_WIDTH / 2);
-	  LargeY = (double)(MouseY - NekoY - BITMAP_HEIGHT);	
+	  LargeX = (double)(MouseX - NekoX - BITMAP_WIDTH * ScaleFactor / 2);
+	  LargeY = (double)(MouseY - NekoY - BITMAP_HEIGHT * ScaleFactor);	
 	}
       }
       else {
-	LargeX = (double)(MouseX - NekoX - BITMAP_WIDTH / 2);
-	LargeY = (double)(MouseY - NekoY - BITMAP_HEIGHT);
+	LargeX = (double)(MouseX - NekoX - BITMAP_WIDTH * ScaleFactor / 2);
+	LargeY = (double)(MouseY - NekoY - BITMAP_HEIGHT * ScaleFactor);
       }
     }
     else {
-      LargeX = (double)(MouseX - NekoX - BITMAP_WIDTH / 2);
-      LargeY = (double)(MouseY - NekoY - BITMAP_HEIGHT);
+      LargeX = (double)(MouseX - NekoX - BITMAP_WIDTH * ScaleFactor / 2);
+      LargeY = (double)(MouseY - NekoY - BITMAP_HEIGHT * ScaleFactor);
     }
 
     DoubleLength = LargeX * LargeX + LargeY * LargeY;
@@ -1120,9 +1186,9 @@ NekoThinkDraw()
 	} else if ((NekoMoveDy < 0 && NekoY <= 0)
 		   || (ToFocus && theTarget != None && NekoY > MouseY)){
 	    SetNekoState(NEKO_U_TOGI);
-	} else if ((NekoMoveDy > 0 && NekoY >= WindowHeight - BITMAP_HEIGHT)
+	} else if ((NekoMoveDy > 0 && NekoY >= WindowHeight - BITMAP_HEIGHT * ScaleFactor)
 		   || (ToFocus && theTarget != None 
-		       &&  NekoY < MouseY - BITMAP_HEIGHT)){
+		       &&  NekoY < MouseY - BITMAP_HEIGHT * ScaleFactor)){
 	    SetNekoState(NEKO_D_TOGI);
 	} else {
 	    SetNekoState(NEKO_JARE);
@@ -1298,8 +1364,8 @@ ProcessNeko()
 
   /* $@G-$N=i4|2=(J */
 
-  NekoX = (WindowWidth - BITMAP_WIDTH / 2) / 2;
-  NekoY = (WindowHeight - BITMAP_HEIGHT / 2) / 2;
+  NekoX = (WindowWidth - BITMAP_WIDTH * ScaleFactor / 2) / 2;
+  NekoY = (WindowHeight - BITMAP_HEIGHT * ScaleFactor / 2) / 2;
 
   NekoLastX = NekoX;
   NekoLastY = NekoY;
@@ -1438,6 +1504,15 @@ GetArguments(argc, argv, theDisplayName)
 	exit(1);
       }
     }
+    else if (strcmp(argv[ArgCounter], "-scale") == 0) {
+      ArgCounter++;
+      if (ArgCounter < argc) {
+	ScaleFactor = atoi(argv[ArgCounter]);
+      } else {
+	fprintf(stderr, "%s: -scale option error.\n", ProgramName);
+	exit(1);
+      }
+    }
     else if (strcmp(argv[ArgCounter], "-time") == 0) {
       ArgCounter++;
       if (ArgCounter < argc) {