Skip to content

Commit

Permalink
Code cleanups.
Browse files Browse the repository at this point in the history
* Moved more types into their own files.
* Simplified polygon by using only one Polygon option type.
* Moved bitmap reading code into a reader extension.
  • Loading branch information
wiesmann committed Apr 17, 2024
1 parent 12c56e9 commit 8baed5d
Show file tree
Hide file tree
Showing 18 changed files with 392 additions and 346 deletions.
18 changes: 18 additions & 0 deletions QuickDrawViewer.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@
E53BBF542BCFD39D00D9350A /* QuickDrawRect.swift in Sources */ = {isa = PBXBuildFile; fileRef = E53BBF522BCFD39D00D9350A /* QuickDrawRect.swift */; };
E53BBF562BCFD41600D9350A /* QuickDrawPolygon.swift in Sources */ = {isa = PBXBuildFile; fileRef = E53BBF552BCFD41600D9350A /* QuickDrawPolygon.swift */; };
E53BBF572BCFD41600D9350A /* QuickDrawPolygon.swift in Sources */ = {isa = PBXBuildFile; fileRef = E53BBF552BCFD41600D9350A /* QuickDrawPolygon.swift */; };
E53BBF592BD05EFB00D9350A /* QuickDrawText.swift in Sources */ = {isa = PBXBuildFile; fileRef = E53BBF582BD05EFB00D9350A /* QuickDrawText.swift */; };
E53BBF5A2BD05EFB00D9350A /* QuickDrawText.swift in Sources */ = {isa = PBXBuildFile; fileRef = E53BBF582BD05EFB00D9350A /* QuickDrawText.swift */; };
E53BBF5C2BD060CE00D9350A /* QuickDrawResolution.swift in Sources */ = {isa = PBXBuildFile; fileRef = E53BBF5B2BD060CE00D9350A /* QuickDrawResolution.swift */; };
E53BBF5D2BD060CE00D9350A /* QuickDrawResolution.swift in Sources */ = {isa = PBXBuildFile; fileRef = E53BBF5B2BD060CE00D9350A /* QuickDrawResolution.swift */; };
E53BBF5F2BD0639700D9350A /* QuickDrawBitMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = E53BBF5E2BD0639700D9350A /* QuickDrawBitMap.swift */; };
E53BBF602BD0639700D9350A /* QuickDrawBitMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = E53BBF5E2BD0639700D9350A /* QuickDrawBitMap.swift */; };
E553E4DC2B6AED62009B1EC2 /* Yuv2.swift in Sources */ = {isa = PBXBuildFile; fileRef = E553E4DB2B6AED62009B1EC2 /* Yuv2.swift */; };
E553E4DD2B6AED62009B1EC2 /* Yuv2.swift in Sources */ = {isa = PBXBuildFile; fileRef = E553E4DB2B6AED62009B1EC2 /* Yuv2.swift */; };
E553E4DF2B6FD9F5009B1EC2 /* QuickTime.swift in Sources */ = {isa = PBXBuildFile; fileRef = E553E4DE2B6FD9F5009B1EC2 /* QuickTime.swift */; };
Expand Down Expand Up @@ -112,6 +118,9 @@
E53BBF4F2BCFD30F00D9350A /* QuickDrawPoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickDrawPoint.swift; sourceTree = "<group>"; };
E53BBF522BCFD39D00D9350A /* QuickDrawRect.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickDrawRect.swift; sourceTree = "<group>"; };
E53BBF552BCFD41600D9350A /* QuickDrawPolygon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickDrawPolygon.swift; sourceTree = "<group>"; };
E53BBF582BD05EFB00D9350A /* QuickDrawText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickDrawText.swift; sourceTree = "<group>"; };
E53BBF5B2BD060CE00D9350A /* QuickDrawResolution.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickDrawResolution.swift; sourceTree = "<group>"; };
E53BBF5E2BD0639700D9350A /* QuickDrawBitMap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickDrawBitMap.swift; sourceTree = "<group>"; };
E553E4DB2B6AED62009B1EC2 /* Yuv2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Yuv2.swift; sourceTree = "<group>"; };
E553E4DE2B6FD9F5009B1EC2 /* QuickTime.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickTime.swift; sourceTree = "<group>"; };
E553E4E12B6FFA53009B1EC2 /* TypeCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TypeCode.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -205,9 +214,12 @@
E553E4E12B6FFA53009B1EC2 /* TypeCode.swift */,
E59CDFA82B42EE0A00D7BB7B /* PackBit.swift */,
E53BBF4F2BCFD30F00D9350A /* QuickDrawPoint.swift */,
E53BBF582BD05EFB00D9350A /* QuickDrawText.swift */,
E53BBF522BCFD39D00D9350A /* QuickDrawRect.swift */,
E53BBF552BCFD41600D9350A /* QuickDrawPolygon.swift */,
E59CDFAA2B42EE0A00D7BB7B /* QuickDrawTypes.swift */,
E53BBF5E2BD0639700D9350A /* QuickDrawBitMap.swift */,
E53BBF5B2BD060CE00D9350A /* QuickDrawResolution.swift */,
E554EE5D2B9DF68800D56DF7 /* QuickDrawPattern.swift */,
E508C4F62B8E9575007686AE /* QuickDrawColor.swift */,
E508C4FF2B936919007686AE /* QuickDrawRegions.swift */,
Expand Down Expand Up @@ -363,9 +375,12 @@
E53BBF482BC3254200D9350A /* Cinepak.swift in Sources */,
E5CDA0272B44155E008DC6D6 /* QuickDrawParser.swift in Sources */,
E59CDFAF2B42EE0A00D7BB7B /* PackBit.swift in Sources */,
E53BBF5F2BD0639700D9350A /* QuickDrawBitMap.swift in Sources */,
E55E05F72B61A74A00EA1AD8 /* RoadPizza.swift in Sources */,
E52FEB052BACC269004E8BB4 /* QuickDrawPort.swift in Sources */,
E53BBF592BD05EFB00D9350A /* QuickDrawText.swift in Sources */,
E553E4DC2B6AED62009B1EC2 /* Yuv2.swift in Sources */,
E53BBF5C2BD060CE00D9350A /* QuickDrawResolution.swift in Sources */,
E53BBF532BCFD39D00D9350A /* QuickDrawRect.swift in Sources */,
E5CDA02D2B4450FB008DC6D6 /* ImageWrapper.swift in Sources */,
E59CDF6E2B42C0E500D7BB7B /* QuickDrawViewerDocument.swift in Sources */,
Expand Down Expand Up @@ -406,6 +421,7 @@
E53BBF462BBB4E5800D9350A /* IntelRaw.swift in Sources */,
E53BBF512BCFD30F00D9350A /* QuickDrawPoint.swift in Sources */,
E5CDA0252B441536008DC6D6 /* QuickDrawErrors.swift in Sources */,
E53BBF5D2BD060CE00D9350A /* QuickDrawResolution.swift in Sources */,
E508C4F52B764CB2007686AE /* Planar.swift in Sources */,
E50ADB972B599CDE009EA7AF /* ContentView.swift in Sources */,
E59CDF812B42C0E600D7BB7B /* QuickDrawViewerTests.swift in Sources */,
Expand All @@ -419,8 +435,10 @@
E50ADB982B599CE1009EA7AF /* QuickDrawViewerApp.swift in Sources */,
E5CDA02E2B4450FB008DC6D6 /* ImageWrapper.swift in Sources */,
E59CDFB62B42EE0A00D7BB7B /* QuickDrawRender.swift in Sources */,
E53BBF5A2BD05EFB00D9350A /* QuickDrawText.swift in Sources */,
E554EE562B9BB4B100D56DF7 /* QuickTimeGraphics.swift in Sources */,
E508C5012B936919007686AE /* QuickDrawRegions.swift in Sources */,
E53BBF602BD0639700D9350A /* QuickDrawBitMap.swift in Sources */,
E53BBF492BC3254200D9350A /* Cinepak.swift in Sources */,
E59CDFB22B42EE0A00D7BB7B /* QuickDrawReader.swift in Sources */,
E52FEB032BAB8C53004E8BB4 /* QuickDrawComment.swift in Sources */,
Expand Down
4 changes: 2 additions & 2 deletions QuickDrawViewer/Animation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ class AnimationImage : PixMapMetadata {
y = Int(try reader.readInt16());
reader.skip(bytes: 6);
}
let encoded = try reader.readUInt8(bytes: reader.remaining);
var index = 0;
let encoded = try reader.readSlice(bytes: reader.remaining);
var index = encoded.startIndex;

while (index < encoded.count - 1) {
let skip = Int(encoded[index]);
Expand Down
6 changes: 4 additions & 2 deletions QuickDrawViewer/Blitting.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ func roundTo(_ value: FixedPoint, multipleOf: Int) -> Int {
/// - u: u chrominance in the -127 - 128 range
/// - v: v chrominance in the -127 - 128 range
/// - Returns: rgb bytes
func yuv2Rgb(y : Double, u: Double, v: Double) -> [UInt8] {
func yuv2Rgb(y : Double, u: Double, v: Double) -> RGB8 {
let r = Int(y + (1.370705 * v));
let g = Int(y - (0.698001 * v) - 0.337633 * u);
let b = Int(y + (1.732446 * u));
return [UInt8(clamping: r), UInt8(clamping: g), UInt8(clamping: b)];
}

func yuv2Rgb(y: UInt8, u: UInt8, v: UInt8) -> [UInt8] {
func yuv2Rgb(y: UInt8, u: UInt8, v: UInt8) -> RGB8 {
let nu = Double(u) - 128;
let nv = Double(v) - 128;
let ny = Double(y);
Expand All @@ -51,6 +51,8 @@ func expandDepth(_ depth : Int) throws -> (Int, Int) {
return (3, 5);
case 24:
return (3, 8);
case 32:
return (3, 8);
default:
throw BlittingError.unsupportedDepth(depth: depth);
}
Expand Down
8 changes: 8 additions & 0 deletions QuickDrawViewer/FixedPoint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,11 @@ public struct FixedPoint : CustomStringConvertible, Comparable, AdditiveArithmet
return FixedPoint(a.value / b.value);
}
}

extension QuickDrawDataReader {

func readFixed() throws -> FixedPoint {
let v = try readInt32();
return FixedPoint(rawValue: Int(v));
}
}
3 changes: 0 additions & 3 deletions QuickDrawViewer/MacPaint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@

import Foundation




/// MacPaint images are fixed size (720 × 576) PackBit compressed bitmaps.
class MacPaintImage : PixMapMetadata {

Expand Down
143 changes: 143 additions & 0 deletions QuickDrawViewer/QuickDrawBitMap.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
//
// QuickDrawBitMap.swift
// QuickDrawViewer
//
// Created by Matthias Wiesmann on 17.04.2024.
//

import Foundation

/// Packing format used in QuickDraw PixMaps
enum QDPackType : UInt16 {
case defaultPack = 0;
case noPack = 1;
case removePadByte = 2;
case pixelRunLength = 3;
case componentRunLength = 4;
}

/// Add-on information for a BitMap that is actually a Pixmap.
/// Confusingly, this is called `PixMap` record in Inside Quickdraw,.
/// even though there is no actual pixel data.
class QDPixMapInfo : CustomStringConvertible {
public var description: String {
var result = "PixMapInfo version: \(version) pack-size: \(packSize) ";
result += "pack-type: \(packType) ";
if resolution != nil {
result += "resolution: \(resolution!) ";
}
result += "pixel type: \(pixelType) ";
result += "pixel size: \(pixelSize) ";
result += "composant count: \(cmpCount) ";
result += "composant size: \(cmpSize) ";
result += "plane byte: \(planeByte) ";
result += "clut Id: \(clutId) ";
if clut != nil {
result += "clut: \(clut!)";
}
return result;
}

var version : Int = 0;
var packType : QDPackType = QDPackType.defaultPack;
var packSize : Int = 0;
var resolution : QDResolution?;
var pixelType : Int = 0;
var pixelSize : Int = 0;
var cmpCount : Int = 0;
var cmpSize : Int = 0;
var planeByte : Int64 = 0;
var clutId : Int32 = 0;
var clutSeed : MacTypeCode = MacTypeCode.zero;
var clut : QDColorTable?;
}


class QDBitMapInfo : CustomStringConvertible, PixMapMetadata {

init(isPacked: Bool) {
self.isPacked = isPacked;
}

var hasShortRows : Bool {
return rowBytes < 250;
}

let isPacked : Bool;
var rowBytes : Int = 0;
var bounds : QDRect = QDRect.empty;
var srcRect : QDRect?;
var dstRect : QDRect?;
var mode : QuickDrawMode = QuickDrawMode.defaultMode;
var data : [UInt8] = [UInt8]();
var pixMapInfo : QDPixMapInfo?;

var destinationRect : QDRect {
return dstRect!;
}

var dimensions: QDDelta {
return bounds.dimensions;
}

var height : Int {
return bounds.dimensions.dv.rounded;
}

var cmpSize : Int {
if let pix_info = pixMapInfo {
return pix_info.cmpSize;
}
return 1;
}

var pixelSize : Int {
if let pix_info = pixMapInfo {
return pix_info.pixelSize;
}
return 1;
}

var clut : QDColorTable? {
if let pix_info = pixMapInfo {
return pix_info.clut!;
}
return QDColorTable.palette1;
}

public var description : String {
let pm = describePixMap(self);
var result = "Bitmap info [\(pm) packed: \(isPacked) ";
result += "Bounds \(bounds) "
if srcRect != nil {
result += "src: \(srcRect!) ";
}
if dstRect != nil {
result += "dst: \(dstRect!) ";
}
result += "Mode: \(mode)]";
if let pixmap = pixMapInfo {
result += "Pixmap: \(pixmap)]";
}
return result;
}
}

extension QuickDrawDataReader {
func readPixMapInfo() throws -> QDPixMapInfo {
let pixMapInfo = QDPixMapInfo();
pixMapInfo.version = Int(try readUInt16());
pixMapInfo.packType = QDPackType(rawValue:try readUInt16())!;
pixMapInfo.packSize = Int(try readUInt32());
pixMapInfo.resolution = try readResolution();
pixMapInfo.pixelType = Int(try readUInt16());
pixMapInfo.pixelSize = Int(try readUInt16());
pixMapInfo.cmpCount = Int(try readUInt16());
pixMapInfo.cmpSize = Int(try readUInt16());
pixMapInfo.planeByte = Int64(try readUInt32());
pixMapInfo.clutId = try readInt32();
pixMapInfo.clutSeed = try readType();
return pixMapInfo;
}
}

8 changes: 8 additions & 0 deletions QuickDrawViewer/QuickDrawColor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,14 @@ extension QuickDrawDataReader {
return ARGB555(rawValue: raw);
}

func readQD1Color() throws -> QD1Color {
let code = try readUInt32();
guard let qd1 = QD1Color(rawValue: code) else {
throw QuickDrawError.unsupportedQD1Color(colorCode: code);
}
return qd1;
}

func readClut() throws -> QDColorTable {
skip(bytes: 4);
let clutFlags = try readUInt16();
Expand Down
20 changes: 3 additions & 17 deletions QuickDrawViewer/QuickDrawComment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,21 +88,6 @@ struct TextPictPayload : FontStateOperation {
let textPictRecord : QDTextPictRecord;
}

struct PolySmoothVerb : OptionSet, CustomStringConvertible {
var description: String {
var result : String = "PolySmoothVerb "
if contains(.polyFrame) {result += " frame"}
if contains(.polyFill) {result += " fill"}
if contains(.polyClose) {result += " close"}
return result;
}

let rawValue: UInt8;
static let polyFrame = PolySmoothVerb(rawValue: 1 << 0);
static let polyFill = PolySmoothVerb(rawValue: 1 << 1) ;
static let polyClose = PolySmoothVerb(rawValue: 1 << 2);
}

struct PostScript : CustomStringConvertible {
var description: String {
return "<PostScript>";
Expand All @@ -116,7 +101,7 @@ enum CommentPayload {
case postScriptPayLoad(postscript: PostScript);
case fontStatePayload(fontOperation: FontStateOperation);
case penStatePayload(penOperation: PenStateOperation);
case polySmoothPayload(verb: PolySmoothVerb);
case polySmoothPayload(verb: PolygonOptions);
case canvasPayload(canvas: CanvasPayload);
case colorPayload(creator: MacTypeCode, color: QDColor);
case unknownPayload(rawType: Int, data: Data);
Expand Down Expand Up @@ -212,7 +197,8 @@ struct CommentOp : OpCode, CustomStringConvertible, CullableOpcode {
let fontOp = TextCenterPayload(center: QDDelta(dv: v, dh: h));
payload = .fontStatePayload(fontOperation: fontOp);
case (.polySmooth, 1):
let verb = PolySmoothVerb(rawValue: try reader.readUInt8());
var verb = PolygonOptions(rawValue: try reader.readUInt8());
verb.insert(.smooth);
payload = .polySmoothPayload(verb: verb);
case (_, 0):
payload = .noPayload;
Expand Down
Loading

0 comments on commit 8baed5d

Please sign in to comment.