1
1
mirror of https://github.com/exyte/Macaw.git synced 2024-09-11 05:05:23 +03:00

added support of kerning to Text. Added example for text rendering.

This commit is contained in:
Andrew Romanov 2019-02-28 13:53:40 +07:00
parent 99c9f79625
commit 2b5f671d60
8 changed files with 157 additions and 10 deletions

View File

@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
49265C832227BB7A00923A66 /* TextsExampleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49265C822227BB7A00923A66 /* TextsExampleView.swift */; };
970AB811D179560D74930D39 /* Pods_Example_macOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5184A00051CAC5E360198B48 /* Pods_Example_macOS.framework */; };
A715CA7D215E472800EE7651 /* ExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A715CA7C215E472800EE7651 /* ExampleViewController.swift */; };
A72862CB1F4308A50033893D /* AnimationsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A72862CA1F4308A50033893D /* AnimationsViewController.swift */; };
@ -25,6 +26,7 @@
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
49265C822227BB7A00923A66 /* TextsExampleView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextsExampleView.swift; sourceTree = "<group>"; };
5184A00051CAC5E360198B48 /* Pods_Example_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Example_macOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
A715CA7C215E472800EE7651 /* ExampleViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExampleViewController.swift; sourceTree = "<group>"; };
A72862CA1F4308A50033893D /* AnimationsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AnimationsViewController.swift; path = Examples/Animations/AnimationsViewController.swift; sourceTree = "<group>"; };
@ -66,6 +68,15 @@
name = Frameworks;
sourceTree = "<group>";
};
49265C812227BB7A00923A66 /* Text */ = {
isa = PBXGroup;
children = (
49265C822227BB7A00923A66 /* TextsExampleView.swift */,
);
name = Text;
path = ../../Example/Example/Examples/Text;
sourceTree = "<group>";
};
4F8946156C3F28DC7B262776 /* Pods */ = {
isa = PBXGroup;
children = (
@ -110,6 +121,7 @@
A759399F1F41C51A000CE329 /* Examples */ = {
isa = PBXGroup;
children = (
49265C812227BB7A00923A66 /* Text */,
A715CA7C215E472800EE7651 /* ExampleViewController.swift */,
A75939A01F41C544000CE329 /* Shapes */,
A75939A61F41C58D000CE329 /* Transform */,
@ -281,7 +293,7 @@
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Example-macOS/Pods-Example-macOS-frameworks.sh",
"${SRCROOT}/Pods/Target Support Files/Pods-Example-macOS/Pods-Example-macOS-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/Macaw/Macaw.framework",
"${BUILT_PRODUCTS_DIR}/SWXMLHash/SWXMLHash.framework",
);
@ -292,7 +304,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Example-macOS/Pods-Example-macOS-frameworks.sh\"\n";
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Example-macOS/Pods-Example-macOS-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
@ -310,6 +322,7 @@
A768EAD81F42C98E00F22A17 /* EventsExampleController.swift in Sources */,
A72862CE1F430DF00033893D /* EasingViewController.swift in Sources */,
A72862CB1F4308A50033893D /* AnimationsViewController.swift in Sources */,
49265C832227BB7A00923A66 /* TextsExampleView.swift in Sources */,
A768EADE1F42CCBC00F22A17 /* AnimationsView.swift in Sources */,
A75939A81F41C5A8000CE329 /* TransformExampleView.swift in Sources */,
A768EADC1F42CC7C00F22A17 /* EasingView.swift in Sources */,

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14313.18"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14460.31"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
@ -111,7 +111,7 @@
<!--Tab View Controller-->
<scene sceneID="HCD-4m-c8h">
<objects>
<tabViewController selectedTabViewItemIndex="0" id="hdB-7F-R9Q" sceneMemberID="viewController">
<tabViewController selectedTabViewItemIndex="6" id="hdB-7F-R9Q" sceneMemberID="viewController">
<tabViewItems>
<tabViewItem identifier="" id="3QN-7z-LrX"/>
<tabViewItem id="1e3-gs-UK8"/>
@ -120,6 +120,7 @@
<tabViewItem id="cOY-ae-H1s"/>
<tabViewItem id="h85-ch-mEO"/>
<tabViewItem id="fd7-0D-v5P"/>
<tabViewItem id="Lcq-hY-C2R"/>
</tabViewItems>
<tabView key="tabView" type="noTabsNoBorder" id="2WP-RT-S1E">
<rect key="frame" x="-57" y="5" width="615" height="95"/>
@ -138,6 +139,7 @@
<segue destination="6Ok-1N-J6E" kind="relationship" relationship="tabItems" id="Oei-AM-VA1"/>
<segue destination="Rn8-Li-WZ2" kind="relationship" relationship="tabItems" id="XnE-5e-LQB"/>
<segue destination="9aj-uf-eJX" kind="relationship" relationship="tabItems" id="dm1-xg-c0C"/>
<segue destination="UV0-nl-E6y" kind="relationship" relationship="tabItems" id="10z-7p-st3"/>
</connections>
</tabViewController>
<customObject id="vzO-zk-Zwd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
@ -345,5 +347,29 @@
</objects>
<point key="canvasLocation" x="57" y="2256"/>
</scene>
<!--Texts-->
<scene sceneID="X4E-CY-SgF">
<objects>
<viewController title="Texts" id="UV0-nl-E6y" sceneMemberID="viewController">
<view key="view" id="Sna-Mq-RHP">
<rect key="frame" x="0.0" y="0.0" width="400" height="300"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="6Dc-5k-wX7" customClass="TextsExampleView" customModule="Example_macOS" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="400" height="300"/>
</customView>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="6Dc-5k-wX7" secondAttribute="bottom" id="MpI-b9-QYF"/>
<constraint firstItem="6Dc-5k-wX7" firstAttribute="top" secondItem="Sna-Mq-RHP" secondAttribute="top" id="VVy-XW-3NP"/>
<constraint firstItem="6Dc-5k-wX7" firstAttribute="leading" secondItem="Sna-Mq-RHP" secondAttribute="leading" id="o8h-7H-raU"/>
<constraint firstAttribute="trailing" secondItem="6Dc-5k-wX7" secondAttribute="trailing" id="pk8-Tx-3CR"/>
</constraints>
</view>
</viewController>
<customObject id="uqV-13-To9" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1128" y="350"/>
</scene>
</scenes>
</document>

View File

@ -8,6 +8,7 @@
/* Begin PBXBuildFile section */
48BC2FE8BD3BF26100D04E07 /* Pods_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0A92F90D3D20D2A289BED45F /* Pods_Example.framework */; };
49265C802227B1EB00923A66 /* TextsExampleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49265C7F2227B1EB00923A66 /* TextsExampleView.swift */; };
5747F9BD1E38B683004E338F /* MorphingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5747F9BC1E38B683004E338F /* MorphingView.swift */; };
574EC43E1CB7DE7F0063F317 /* ShapesExampleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 574EC4341CB7DE7F0063F317 /* ShapesExampleView.swift */; };
574EC4411CB7E2440063F317 /* MenuViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 574EC4401CB7E2440063F317 /* MenuViewController.swift */; };
@ -41,6 +42,7 @@
/* Begin PBXFileReference section */
0A92F90D3D20D2A289BED45F /* Pods_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; };
131DDFA4A9D164CC4B64C3E8 /* Pods-Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-Example/Pods-Example.release.xcconfig"; sourceTree = "<group>"; };
49265C7F2227B1EB00923A66 /* TextsExampleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextsExampleView.swift; sourceTree = "<group>"; };
5747F9BC1E38B683004E338F /* MorphingView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MorphingView.swift; sourceTree = "<group>"; };
574EC4341CB7DE7F0063F317 /* ShapesExampleView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShapesExampleView.swift; sourceTree = "<group>"; };
574EC4401CB7E2440063F317 /* MenuViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MenuViewController.swift; path = Example/MenuViewController.swift; sourceTree = SOURCE_ROOT; };
@ -82,6 +84,14 @@
name = Pods;
sourceTree = "<group>";
};
49265C7E2227B1B200923A66 /* Text */ = {
isa = PBXGroup;
children = (
49265C7F2227B1EB00923A66 /* TextsExampleView.swift */,
);
path = Text;
sourceTree = "<group>";
};
5747F9BB1E38B660004E338F /* Morphing */ = {
isa = PBXGroup;
children = (
@ -93,6 +103,7 @@
574EC4271CB7DE7F0063F317 /* Examples */ = {
isa = PBXGroup;
children = (
49265C7E2227B1B200923A66 /* Text */,
574EC4331CB7DE7F0063F317 /* Shapes */,
6699B7CE1DFFE8B90072585E /* Transform */,
574EC4421CBB607E0063F317 /* Animations */,
@ -353,6 +364,7 @@
5BAE3CB120C54E3D006BEF51 /* FiltersViewController.swift in Sources */,
57AF398C1E67E9DB00F0BFE2 /* EventsExampleController.swift in Sources */,
B04416FA1E041A420016BC50 /* EasingView.swift in Sources */,
49265C802227B1EB00923A66 /* TextsExampleView.swift in Sources */,
574EC4411CB7E2440063F317 /* MenuViewController.swift in Sources */,
574EC43E1CB7DE7F0063F317 /* ShapesExampleView.swift in Sources */,
B04416FC1E04282A0016BC50 /* EasingExampleController.swift in Sources */,

View File

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="pJi-Pa-uLB">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="pJi-Pa-uLB">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
@ -353,5 +353,35 @@
</objects>
<point key="canvasLocation" x="-82.400000000000006" y="1915.5922038980511"/>
</scene>
<!--Texts-->
<scene sceneID="bTW-zB-L9Y">
<objects>
<viewController storyboardIdentifier="TextsViewController" title="Texts" id="WKi-9n-Pbh" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="ECn-an-4YB"/>
<viewControllerLayoutGuide type="bottom" id="dI3-Tc-JoV"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="eF2-bs-oUF">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hPm-Wd-j2e" customClass="TextsExampleView" customModule="Example" customModuleProvider="target">
<rect key="frame" x="0.0" y="20" width="375" height="647"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="hPm-Wd-j2e" firstAttribute="leading" secondItem="eF2-bs-oUF" secondAttribute="leading" id="YKn-kZ-CQC"/>
<constraint firstItem="hPm-Wd-j2e" firstAttribute="top" secondItem="ECn-an-4YB" secondAttribute="bottom" id="gIj-5H-QLF"/>
<constraint firstItem="dI3-Tc-JoV" firstAttribute="top" secondItem="hPm-Wd-j2e" secondAttribute="bottom" id="kLf-IH-dyy"/>
<constraint firstAttribute="trailing" secondItem="hPm-Wd-j2e" secondAttribute="trailing" id="xIq-DI-gT3"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="oGc-AF-UNq" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-113" y="1196"/>
</scene>
</scenes>
</document>

View File

@ -0,0 +1,46 @@
//
// TextsExampleView.swift
// Example
//
// Created by Andrew Romanov on 28/02/2019.
// Copyright © 2019 Exyte. All rights reserved.
//
import Macaw
class TextsExampleView: MacawView {
required init?(coder aDecoder: NSCoder) {
let text1 = TextsExampleView.newText("Font", .move(dx: 100, dy: 40))
text1.font = Font(name: "Helvetica", size: 20, weight: "normal")
let text2 = TextsExampleView.newText("Stroke", .move(dx: 100, dy: 200))
text2.font = Font(name: "Helvetica", size: 40, weight: "normal")
text2.fill = Color(val: 0xFF0000);
text2.stroke = Stroke(fill: Color(val: 0x00FF00), width: 20.0);
let text4 = TextsExampleView.newText("Stroke", .move(dx: 100, dy: 200))
text4.font = Font(name: "Helvetica", size: 40, weight: "normal")
text4.fill = Color(val: 0xFF0000);
let text3 = TextsExampleView.newText("Kern inc", .move(dx: 100, dy: 250))
text3.kern = 3.0
let text5 = TextsExampleView.newText("Kern dec", .move(dx: 100, dy: 300))
text5.kern = -1.0
let group = Group(
contents: [
text1, text2, text3, text4, text5
]
)
super.init(node: group, coder: aDecoder)
}
fileprivate static func newText(_ text: String, _ place: Transform, baseline: Baseline = .bottom) -> Text {
return Text(text: text, fill: Color.black, align: .mid, baseline: baseline, place: place)
}
}

View File

@ -12,7 +12,8 @@ open class MenuViewController: UIViewController, UITableViewDataSource, UITableV
"EasingExampleController",
"MorphingExampleController",
"EventsExampleController",
"FiltersViewController"
"FiltersViewController",
"TextsViewController"
].map {
UIStoryboard(name: "Main", bundle: .none).instantiateViewController(withIdentifier: $0)
}

View File

@ -41,14 +41,21 @@ open class Text: Node {
get { return baselineVar.value }
set(val) { baselineVar.value = val }
}
public let kernVar: Variable<Float>
open var kern: Float {
get { return kernVar.value }
set(val) { kernVar.value = val}
}
public init(text: String, font: Font? = nil, fill: Fill? = Color.black, stroke: Stroke? = nil, align: Align = .min, baseline: Baseline = .top, place: Transform = Transform.identity, opaque: Bool = true, opacity: Double = 1, clip: Locus? = nil, mask: Node? = nil, effect: Effect? = nil, visible: Bool = true, tag: [String] = []) {
public init(text: String, font: Font? = nil, fill: Fill? = Color.black, stroke: Stroke? = nil, align: Align = .min, baseline: Baseline = .top, kern: Float = 0.0, place: Transform = Transform.identity, opaque: Bool = true, opacity: Double = 1, clip: Locus? = nil, mask: Node? = nil, effect: Effect? = nil, visible: Bool = true, tag: [String] = []) {
self.textVar = Variable<String>(text)
self.fontVar = Variable<Font?>(font)
self.fillVar = Variable<Fill?>(fill)
self.strokeVar = Variable<Stroke?>(stroke)
self.alignVar = Variable<Align>(align)
self.baselineVar = Variable<Baseline>(baseline)
self.kernVar = Variable<Float>(kern)
super.init(
place: place,
opaque: opaque,
@ -75,6 +82,7 @@ open class Text: Node {
}
var stringAttributes: [NSAttributedString.Key: AnyObject] = [:]
stringAttributes[NSAttributedString.Key.font] = font
stringAttributes[NSAttributedString.Key.kern] = NSNumber(value: self.kern)
let size = (text as NSString).size(withAttributes: stringAttributes)
return Rect(
x: calculateAlignmentOffset(font: font),

View File

@ -35,6 +35,7 @@ class TextRenderer: NodeRenderer {
observe(text.strokeVar)
observe(text.alignVar)
observe(text.baselineVar)
observe(text.kernVar)
}
override func doRender(in context: CGContext, force: Bool, opacity: Double, coloringMode: ColoringMode = .rgb) {
@ -65,6 +66,10 @@ class TextRenderer: NodeRenderer {
}
attributes[NSAttributedString.Key.strokeWidth] = width as NSObject?
}
if text.kern != 0.0 {
attributes[NSAttributedString.Key.kern] = NSNumber(value: text.kern)
}
if attributes.count > 1 {
MGraphicsPushContext(context)
message.draw(in: getBounds(font), withAttributes: attributes)
@ -129,7 +134,13 @@ class TextRenderer: NodeRenderer {
return .zero
}
let textAttributes = [NSAttributedString.Key.font: font]
var textAttributes : [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: font]
if (text.kern != 0.0){
textAttributes[NSAttributedString.Key.kern] = NSNumber(value: text.kern)
}
if let stroke = text.stroke {
textAttributes[NSAttributedString.Key.strokeWidth] = NSNumber(value: stroke.width)
}
let textSize = NSString(string: text.text).size(withAttributes: textAttributes)
return CGRect(x: calculateAlignmentOffset(text, font: font),
y: calculateBaselineOffset(text, font: font),