@breakside/jskit 2026.11.0 → 2026.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Frameworks/DOM.jsframework/Info.json +2 -2
- package/Frameworks/DOM.jsframework/io.breakside.JSKit.DOM-bundle.js +2 -2
- package/Frameworks/FontKit.jsframework/Info.json +2 -2
- package/Frameworks/FontKit.jsframework/JS/FNTOpenTypeFont.js +331 -22
- package/Frameworks/FontKit.jsframework/io.breakside.JSKit.FontKit-bundle.js +2 -2
- package/Frameworks/Foundation.jsframework/Info.json +2 -2
- package/Frameworks/Foundation.jsframework/JS/JSAttributedString.js +56 -1
- package/Frameworks/Foundation.jsframework/JS/JSContext.js +44 -17
- package/Frameworks/Foundation.jsframework/JS/JSCubicBezier.js +54 -1
- package/Frameworks/Foundation.jsframework/JS/JSFont.js +8 -9
- package/Frameworks/Foundation.jsframework/JS/JSGradient.js +28 -2
- package/Frameworks/Foundation.jsframework/JS/JSImage+HTML.js +27 -1
- package/Frameworks/Foundation.jsframework/JS/JSNumberFormatter.js +23 -1
- package/Frameworks/Foundation.jsframework/JS/JSPath.js +194 -6
- package/Frameworks/Foundation.jsframework/JS/JSPoint.js +56 -0
- package/Frameworks/Foundation.jsframework/JS/JSTextRun.js +21 -4
- package/Frameworks/Foundation.jsframework/JS/JSTextStorage.js +5 -0
- package/Frameworks/Foundation.jsframework/JS/JSTextTypesetter.js +6 -1
- package/Frameworks/Foundation.jsframework/JS/JSXMLParser.js +1 -1
- package/Frameworks/Foundation.jsframework/io.breakside.JSKit.Foundation-bundle.js +2 -2
- package/Frameworks/Foundation.jsframework/sources.json +1 -0
- package/Frameworks/SecurityKit.jsframework/Info.json +2 -2
- package/Frameworks/SecurityKit.jsframework/io.breakside.JSKit.SecurityKit-bundle.js +2 -2
- package/Info.json +2 -2
- package/Node/io.breakside.jskit-bundle.js +2 -2
- package/Root/Frameworks/APIKit/Info.yaml +1 -1
- package/Root/Frameworks/APIKitTesting/Info.yaml +1 -1
- package/Root/Frameworks/AuthKit/Info.yaml +1 -1
- package/Root/Frameworks/CSSOM/CSSTokenizer.js +633 -470
- package/Root/Frameworks/CSSOM/Info.yaml +1 -1
- package/Root/Frameworks/ChartKit/Info.yaml +1 -1
- package/Root/Frameworks/ConferenceKit/Info.yaml +1 -1
- package/Root/Frameworks/DBKit/Info.yaml +1 -1
- package/Root/Frameworks/DOM/Info.yaml +1 -1
- package/Root/Frameworks/Dispatch/Info.yaml +1 -1
- package/Root/Frameworks/FontKit/FNTOpenTypeFont.js +331 -22
- package/Root/Frameworks/FontKit/Info.yaml +1 -1
- package/Root/Frameworks/Foundation/Info.yaml +1 -1
- package/Root/Frameworks/Foundation/JSAttributedString.js +56 -1
- package/Root/Frameworks/Foundation/JSContext.js +44 -17
- package/Root/Frameworks/Foundation/JSCubicBezier.js +54 -1
- package/Root/Frameworks/Foundation/JSFont.js +8 -9
- package/Root/Frameworks/Foundation/JSGradient.js +28 -2
- package/Root/Frameworks/Foundation/JSImage+HTML.js +27 -1
- package/Root/Frameworks/Foundation/JSNumberFormatter.js +23 -1
- package/Root/Frameworks/Foundation/JSPath.js +194 -6
- package/Root/Frameworks/Foundation/JSPoint.js +56 -0
- package/Root/Frameworks/Foundation/JSTextRun.js +21 -4
- package/Root/Frameworks/Foundation/JSTextStorage.js +5 -0
- package/Root/Frameworks/Foundation/JSTextTypesetter.js +6 -1
- package/Root/Frameworks/Foundation/JSXMLParser.js +1 -1
- package/Root/Frameworks/ImageKit/IKHTMLCanvasBitmapContext.js +187 -101
- package/Root/Frameworks/ImageKit/IKNodeBitmapContext.js +4 -4
- package/Root/Frameworks/ImageKit/Info.yaml +1 -1
- package/Root/Frameworks/MediaKit/Info.yaml +1 -1
- package/Root/Frameworks/MediaKitUI/Info.yaml +1 -1
- package/Root/Frameworks/NotificationKit/Info.yaml +1 -1
- package/Root/Frameworks/PDFKit/Info.yaml +1 -1
- package/Root/Frameworks/QRKit/Info.yaml +1 -1
- package/Root/Frameworks/SearchKit/Info.yaml +1 -1
- package/Root/Frameworks/SecurityKit/Info.yaml +1 -1
- package/Root/Frameworks/ServerKit/Info.yaml +1 -1
- package/Root/Frameworks/ServerKitTesting/Info.yaml +1 -1
- package/Root/Frameworks/TestKit/Info.yaml +1 -1
- package/Root/Frameworks/TestKit/TKAssert.js +4 -4
- package/Root/Frameworks/UIKit/Info.yaml +1 -1
- package/Root/Frameworks/UIKit/UIApplication.js +9 -1
- package/Root/Frameworks/UIKit/UICollectionView.js +4 -0
- package/Root/Frameworks/UIKit/UIColorPanel.js +46 -0
- package/Root/Frameworks/UIKit/UIColorWell.js +8 -0
- package/Root/Frameworks/UIKit/UIHTMLDisplayServer.js +21 -2
- package/Root/Frameworks/UIKit/UIHTMLDisplayServerCanvasContext.js +150 -69
- package/Root/Frameworks/UIKit/UIHTMLTextRun.js +5 -0
- package/Root/Frameworks/UIKit/UIHTMLTextTypesetter.js +18 -3
- package/Root/Frameworks/UIKit/UIListView.js +7 -5
- package/Root/Frameworks/UIKit/UIMenu.js +50 -32
- package/Root/Frameworks/UIKit/UIMenuItem.js +12 -0
- package/Root/Frameworks/UIKit/UIMenuView.js +27 -5
- package/Root/Frameworks/UIKit/UIPlatform.js +7 -0
- package/Root/Frameworks/UIKit/UIPopupButton.js +7 -1
- package/Root/Frameworks/UIKit/UIResponder.js +8 -0
- package/Root/Frameworks/UIKit/UITextEditor.js +31 -7
- package/Root/Frameworks/UIKit/UITextField.js +7 -0
- package/Root/Frameworks/UIKit/UITokenField.js +65 -0
- package/Root/Frameworks/UIKit/UIToolbar.js +1 -1
- package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
- package/package.json +1 -1
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
|
|
22
22
|
JSProtocol("UIColorPanelDelegate", JSProtocol, {
|
|
23
23
|
|
|
24
|
+
colorPanelDidBeginEditing: function(panel, event){},
|
|
25
|
+
colorPanelDidEndEditing: function(panel, event){},
|
|
24
26
|
colorPanelDidChangeColor: function(panel, color){},
|
|
25
27
|
colorPanelDidClose: function(panel){}
|
|
26
28
|
|
|
@@ -239,8 +241,14 @@ JSClass("UIColorPanelViewController", UIViewController, {
|
|
|
239
241
|
this.hexField.leftAccessoryVisibility = UITextField.AccessoryVisibility.always;
|
|
240
242
|
|
|
241
243
|
this.saturationBrightnessControl.addAction(this.saturationBrightnessChanged, this);
|
|
244
|
+
this.saturationBrightnessControl.addAction(this.saturationBrightnessEditingBegan, this, UIControl.Event.editingDidBegin);
|
|
245
|
+
this.saturationBrightnessControl.addAction(this.saturationBrightnessEditingEnded, this, UIControl.Event.editingDidEnd);
|
|
242
246
|
this.hueSlider.addAction(this.hueSliderChanged, this);
|
|
247
|
+
this.hueSlider.addAction(this.hueSliderEditingBegan, this, UIControl.Event.editingDidBegin);
|
|
248
|
+
this.hueSlider.addAction(this.hueSliderEditingEnded, this, UIControl.Event.editingDidEnd);
|
|
243
249
|
this.alphaSlider.addAction(this.alphaSliderChanged, this);
|
|
250
|
+
this.alphaSlider.addAction(this.alphaSliderEditingBegan, this, UIControl.Event.editingDidBegin);
|
|
251
|
+
this.alphaSlider.addAction(this.alphaSliderEditingEnded, this, UIControl.Event.editingDidEnd);
|
|
244
252
|
this.hexField.addAction(this.hexFieldChanged, this);
|
|
245
253
|
this.component1Field.addAction(this.component1FieldChanged, this);
|
|
246
254
|
this.component2Field.addAction(this.component2FieldChanged, this);
|
|
@@ -308,6 +316,18 @@ JSClass("UIColorPanelViewController", UIViewController, {
|
|
|
308
316
|
this.notifyDelegateOfColor();
|
|
309
317
|
},
|
|
310
318
|
|
|
319
|
+
saturationBrightnessEditingBegan: function(sender, event){
|
|
320
|
+
if (this.delegate && this.delegate.colorPanelDidBeginEditing){
|
|
321
|
+
this.delegate.colorPanelDidBeginEditing(this, event);
|
|
322
|
+
}
|
|
323
|
+
},
|
|
324
|
+
|
|
325
|
+
saturationBrightnessEditingEnded: function(sender, event){
|
|
326
|
+
if (this.delegate && this.delegate.colorPanelDidEndEditing){
|
|
327
|
+
this.delegate.colorPanelDidEndEditing(this, event);
|
|
328
|
+
}
|
|
329
|
+
},
|
|
330
|
+
|
|
311
331
|
hueSliderChanged: function(slider){
|
|
312
332
|
this._hsvComponents[0] = slider.value;
|
|
313
333
|
this._recalculateColorFromHSV();
|
|
@@ -315,12 +335,36 @@ JSClass("UIColorPanelViewController", UIViewController, {
|
|
|
315
335
|
this.notifyDelegateOfColor();
|
|
316
336
|
},
|
|
317
337
|
|
|
338
|
+
hueSliderEditingBegan: function(sender, event){
|
|
339
|
+
if (this.delegate && this.delegate.colorPanelDidBeginEditing){
|
|
340
|
+
this.delegate.colorPanelDidBeginEditing(this, event);
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
|
|
344
|
+
hueSliderEditingEnded: function(sender, event){
|
|
345
|
+
if (this.delegate && this.delegate.colorPanelDidEndEditing){
|
|
346
|
+
this.delegate.colorPanelDidEndEditing(this, event);
|
|
347
|
+
}
|
|
348
|
+
},
|
|
349
|
+
|
|
318
350
|
alphaSliderChanged: function(slider){
|
|
319
351
|
this._color = this._color.colorWithAlpha(slider.value);
|
|
320
352
|
this._alphaChanged(slider);
|
|
321
353
|
this.notifyDelegateOfColor();
|
|
322
354
|
},
|
|
323
355
|
|
|
356
|
+
alphaSliderEditingBegan: function(sender, event){
|
|
357
|
+
if (this.delegate && this.delegate.colorPanelDidBeginEditing){
|
|
358
|
+
this.delegate.colorPanelDidBeginEditing(this, event);
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
|
|
362
|
+
alphaSliderEditingEnded: function(sender, event){
|
|
363
|
+
if (this.delegate && this.delegate.colorPanelDidEndEditing){
|
|
364
|
+
this.delegate.colorPanelDidEndEditing(this, event);
|
|
365
|
+
}
|
|
366
|
+
},
|
|
367
|
+
|
|
324
368
|
component1FieldChanged: function(textField){
|
|
325
369
|
var value = textField.integerValue;
|
|
326
370
|
if (isNaN(value)){
|
|
@@ -829,6 +873,7 @@ JSClass("UIColorPanelTwoAxisSlider", UIControl, {
|
|
|
829
873
|
initialOffset: JSPoint.Zero,
|
|
830
874
|
};
|
|
831
875
|
this.active = true;
|
|
876
|
+
this.sendActionsForEvents(UIControl.Event.editingDidBegin, event);
|
|
832
877
|
if (!isOnKnob){
|
|
833
878
|
this.value = this.valueForPoint(location);
|
|
834
879
|
this.didChangeValueForBinding('value');
|
|
@@ -852,6 +897,7 @@ JSClass("UIColorPanelTwoAxisSlider", UIControl, {
|
|
|
852
897
|
_endSlide: function(event){
|
|
853
898
|
if (this.active){
|
|
854
899
|
this.active = false;
|
|
900
|
+
this.sendActionsForEvents(UIControl.Event.editingDidEnd, event);
|
|
855
901
|
}
|
|
856
902
|
this._drag = null;
|
|
857
903
|
},
|
|
@@ -211,6 +211,14 @@ JSClass("UIColorWell", UIControl, {
|
|
|
211
211
|
// ----------------------------------------------------------------------
|
|
212
212
|
// MARK: - Color Panel
|
|
213
213
|
|
|
214
|
+
colorPanelDidBeginEditing: function(panel, event){
|
|
215
|
+
this.sendActionsForEvents(UIControl.Event.editingDidBegin, event);
|
|
216
|
+
},
|
|
217
|
+
|
|
218
|
+
colorPanelDidEndEditing: function(panel, event){
|
|
219
|
+
this.sendActionsForEvents(UIControl.Event.editingDidEnd, event);
|
|
220
|
+
},
|
|
221
|
+
|
|
214
222
|
colorPanelDidChangeColor: function(panel, color){
|
|
215
223
|
this._changeColor(color);
|
|
216
224
|
},
|
|
@@ -419,12 +419,31 @@ JSClass("UIHTMLDisplayServer", UIDisplayServer, {
|
|
|
419
419
|
}
|
|
420
420
|
insertedLayersByParentContext[info.parentContext.objectID].push(info.layer);
|
|
421
421
|
}
|
|
422
|
+
var parentContext;
|
|
423
|
+
var context;
|
|
424
|
+
var i, l;
|
|
422
425
|
for (var contextId in insertedLayersByParentContext){
|
|
423
426
|
insertedLayersByParentContext[contextId].sort(function(a, b){
|
|
424
427
|
return a.sublayerIndex - b.sublayerIndex;
|
|
425
428
|
});
|
|
426
|
-
|
|
427
|
-
|
|
429
|
+
parentContext = parentContextsById[contextId];
|
|
430
|
+
// If a layer's element is already in the parent element (meaning it
|
|
431
|
+
// is just changing order), first remove it from the parent element
|
|
432
|
+
// so sublayer index calculations will work correctly.
|
|
433
|
+
// NOTE: UIHTMLDisplayServerCanvasContext.insertSublayerContext()
|
|
434
|
+
// already checked for this, but its check only worked when moving a
|
|
435
|
+
// single layer. When adding moving and adding multiple layers at
|
|
436
|
+
// a time, we need first to remove all elements that moving before
|
|
437
|
+
// trying to insert or re-insert any of moved/added elements.
|
|
438
|
+
for (i = 0, l = insertedLayersByParentContext[contextId].length; i < l; ++i){
|
|
439
|
+
layer = insertedLayersByParentContext[contextId][i];
|
|
440
|
+
context = this.contextsByObjectID[layer.objectID];
|
|
441
|
+
if (context && context.element.parentNode === parentContext.element){
|
|
442
|
+
parentContext.element.removeChild(context.element);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
for (i = 0, l = insertedLayersByParentContext[contextId].length; i < l; ++i){
|
|
446
|
+
this._insertLayerIntoDOM(insertedLayersByParentContext[contextId][i], parentContext);
|
|
428
447
|
}
|
|
429
448
|
}
|
|
430
449
|
this._insertedLayers = {};
|
|
@@ -578,6 +578,18 @@ JSClass("UIHTMLDisplayServerCanvasContext", UIHTMLDisplayServerContext, {
|
|
|
578
578
|
},
|
|
579
579
|
|
|
580
580
|
fillMaskedRect: function(rect, maskImage){
|
|
581
|
+
if (maskImage._htmlImage !== undefined && maskImage._htmlImage !== null){
|
|
582
|
+
var maskCanvas = this.canvasContext.canvas.ownerDocument.createElement("canvas");
|
|
583
|
+
maskCanvas.width = rect.size.width;
|
|
584
|
+
maskCanvas.height = rect.size.height;
|
|
585
|
+
var maskContext = maskCanvas.getContext('2d');
|
|
586
|
+
maskContext.fillStyle = this.state.fillColor.cssString();
|
|
587
|
+
maskContext.fillRect(0, 0, rect.size.width, rect.size.height);
|
|
588
|
+
maskContext.globalCompositeOperation = 'destination-in';
|
|
589
|
+
maskContext.drawImage(maskImage._htmlImage, 0, 0, rect.size.width, rect.size.height);
|
|
590
|
+
this.canvasContext.drawImage(maskCanvas, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
581
593
|
var imageElement = this._dequeueReusableImageElement();
|
|
582
594
|
this._positionImageElement(imageElement, maskImage, rect);
|
|
583
595
|
var url = maskImage.htmlURLString();
|
|
@@ -602,6 +614,10 @@ JSClass("UIHTMLDisplayServerCanvasContext", UIHTMLDisplayServerContext, {
|
|
|
602
614
|
_imageElementIndex: 0,
|
|
603
615
|
|
|
604
616
|
drawImage: function(image, rect){
|
|
617
|
+
if (image._htmlImage !== null && image._htmlImage !== undefined){
|
|
618
|
+
this.canvasContext.drawImage(image._htmlImage, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
605
621
|
if (image !== null){
|
|
606
622
|
var url = image.htmlURLString();
|
|
607
623
|
// FIXME: proof of concept, but really shouldn't do async
|
|
@@ -687,57 +703,96 @@ JSClass("UIHTMLDisplayServerCanvasContext", UIHTMLDisplayServerContext, {
|
|
|
687
703
|
|
|
688
704
|
drawLinearGradient: function(gradient, rect){
|
|
689
705
|
this.canvasContext.save();
|
|
690
|
-
var canvasGradient = this.canvasContext
|
|
691
|
-
rect.origin.x + gradient.start.x * rect.size.width,
|
|
692
|
-
rect.origin.y + gradient.start.y * rect.size.height,
|
|
693
|
-
rect.origin.x + gradient.end.x * rect.size.width,
|
|
694
|
-
rect.origin.y + gradient.end.y * rect.size.height
|
|
695
|
-
);
|
|
696
|
-
var stop;
|
|
697
|
-
for (var i = 0, l = gradient.stops.length; i < l; ++i){
|
|
698
|
-
stop = gradient.stops[i];
|
|
699
|
-
canvasGradient.addColorStop(stop.position, stop.color.cssString());
|
|
700
|
-
}
|
|
706
|
+
var canvasGradient = this._linearGradientForCanvasContext(this.canvasContext, gradient, rect);
|
|
701
707
|
this.canvasContext.fillStyle = canvasGradient;
|
|
702
708
|
this.canvasContext.fillRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
|
|
703
709
|
this.canvasContext.restore();
|
|
704
710
|
},
|
|
705
711
|
|
|
706
712
|
drawRadialGradient: function(gradient, rect){
|
|
707
|
-
var r0 = 0;
|
|
708
|
-
var start = JSPoint(
|
|
709
|
-
rect.origin.x + gradient.start.x * rect.size.width,
|
|
710
|
-
rect.origin.y + gradient.start.y * rect.size.height
|
|
711
|
-
);
|
|
712
|
-
var end = JSPoint(
|
|
713
|
-
rect.origin.x + gradient.end.x * rect.size.width,
|
|
714
|
-
rect.origin.y + gradient.end.y * rect.size.height
|
|
715
|
-
);
|
|
716
|
-
var r1 = start.distanceToPoint(end);
|
|
717
713
|
this.canvasContext.save();
|
|
718
|
-
var canvasGradient = this.canvasContext
|
|
719
|
-
start.x,
|
|
720
|
-
start.y,
|
|
721
|
-
r0,
|
|
722
|
-
start.x,
|
|
723
|
-
start.y,
|
|
724
|
-
r1
|
|
725
|
-
);
|
|
726
|
-
var stop;
|
|
727
|
-
for (var i = 0, l = gradient.stops.length; i < l; ++i){
|
|
728
|
-
stop = gradient.stops[i];
|
|
729
|
-
canvasGradient.addColorStop(stop.position, stop.color.cssString());
|
|
730
|
-
}
|
|
714
|
+
var canvasGradient = this._radialGradientForCanvasContext(this.canvasContext, gradient, rect);
|
|
731
715
|
this.canvasContext.fillStyle = canvasGradient;
|
|
732
716
|
this.canvasContext.fillRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
|
|
733
717
|
this.canvasContext.restore();
|
|
734
718
|
},
|
|
735
719
|
|
|
736
|
-
|
|
720
|
+
drawMaskedLinearGradient: function(gradient, rect, maskImage){
|
|
721
|
+
if (maskImage._htmlImage !== undefined && maskImage._htmlImage !== null){
|
|
722
|
+
var maskCanvas = this.canvasContext.canvas.ownerDocument.createElement("canvas");
|
|
723
|
+
maskCanvas.width = rect.size.width;
|
|
724
|
+
maskCanvas.height = rect.size.height;
|
|
725
|
+
var maskContext = maskCanvas.getContext('2d');
|
|
726
|
+
var canvasGradient = this._linearGradientForCanvasContext(maskContext, gradient, JSRect(JSPoint.Zero, rect.size));
|
|
727
|
+
maskContext.fillStyle = canvasGradient;
|
|
728
|
+
maskContext.fillRect(0, 0, rect.size.width, rect.size.height);
|
|
729
|
+
maskContext.globalCompositeOperation = 'destination-in';
|
|
730
|
+
maskContext.drawImage(maskImage._htmlImage, 0, 0, rect.size.width, rect.size.height);
|
|
731
|
+
this.canvasContext.drawImage(maskCanvas, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
|
|
732
|
+
return;
|
|
733
|
+
}
|
|
734
|
+
var imageElement = this._dequeueReusableImageElement();
|
|
735
|
+
this._positionImageElement(imageElement, maskImage, rect);
|
|
736
|
+
var url = maskImage.htmlURLString();
|
|
737
|
+
var cssURL = "url('" + url + "')";
|
|
738
|
+
imageElement.style.maskImage = cssURL;
|
|
739
|
+
imageElement.style.maskSize = '100% 100%';
|
|
740
|
+
imageElement.style.webkitMaskImage = cssURL;
|
|
741
|
+
imageElement.style.webkitMaskSize = '100% 100%';
|
|
742
|
+
imageElement.style.backgroundImage = gradient.cssString(rect.size);
|
|
743
|
+
this._insertChildElement(imageElement);
|
|
744
|
+
},
|
|
745
|
+
|
|
746
|
+
drawMaskedRadialGradient: function(gradient, rect, maskImage){
|
|
747
|
+
if (maskImage._htmlImage !== undefined && maskImage._htmlImage !== null){
|
|
748
|
+
var maskCanvas = this.canvasContext.canvas.ownerDocument.createElement("canvas");
|
|
749
|
+
maskCanvas.width = rect.size.width;
|
|
750
|
+
maskCanvas.height = rect.size.height;
|
|
751
|
+
var maskContext = maskCanvas.getContext('2d');
|
|
752
|
+
var canvasGradient = this._radialGradientForCanvasContext(maskContext, gradient, JSRect(JSPoint.Zero, rect.size));
|
|
753
|
+
maskContext.fillStyle = canvasGradient;
|
|
754
|
+
maskContext.fillRect(0, 0, rect.size.width, rect.size.height);
|
|
755
|
+
maskContext.globalCompositeOperation = 'destination-in';
|
|
756
|
+
maskContext.drawImage(maskImage._htmlImage, 0, 0, rect.size.width, rect.size.height);
|
|
757
|
+
this.canvasContext.drawImage(maskCanvas, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
760
|
+
var imageElement = this._dequeueReusableImageElement();
|
|
761
|
+
this._positionImageElement(imageElement, maskImage, rect);
|
|
762
|
+
var url = maskImage.htmlURLString();
|
|
763
|
+
var cssURL = "url('" + url + "')";
|
|
764
|
+
imageElement.style.maskImage = cssURL;
|
|
765
|
+
imageElement.style.maskSize = '100% 100%';
|
|
766
|
+
imageElement.style.webkitMaskImage = cssURL;
|
|
767
|
+
imageElement.style.webkitMaskSize = '100% 100%';
|
|
768
|
+
imageElement.style.backgroundImage = gradient.radialCSSString(rect.size);
|
|
769
|
+
this._insertChildElement(imageElement);
|
|
770
|
+
},
|
|
771
|
+
|
|
772
|
+
drawLinearGradientStroke: function(gradient, path, alternateRect){
|
|
773
|
+
var rect = path.boundingRect;
|
|
774
|
+
this.canvasContext.save();
|
|
775
|
+
this.addPath(path);
|
|
776
|
+
var canvasGradient = this._linearGradientForCanvasContext(this.canvasContext, gradient, alternateRect || rect);
|
|
777
|
+
this.canvasContext.strokeStyle = canvasGradient;
|
|
778
|
+
this.canvasContext.stroke();
|
|
779
|
+
this.canvasContext.restore();
|
|
780
|
+
this.beginPath();
|
|
781
|
+
},
|
|
782
|
+
|
|
783
|
+
drawRadialGradientStroke: function(gradient, path, alternateRect){
|
|
737
784
|
var rect = path.boundingRect;
|
|
738
785
|
this.canvasContext.save();
|
|
739
786
|
this.addPath(path);
|
|
740
|
-
var canvasGradient = this.canvasContext
|
|
787
|
+
var canvasGradient = this._radialGradientForCanvasContext(this.canvasContext, gradient, alternateRect || rect);
|
|
788
|
+
this.canvasContext.strokeStyle = canvasGradient;
|
|
789
|
+
this.canvasContext.stroke();
|
|
790
|
+
this.canvasContext.restore();
|
|
791
|
+
this.beginPath();
|
|
792
|
+
},
|
|
793
|
+
|
|
794
|
+
_linearGradientForCanvasContext: function(canvasContext, gradient, rect){
|
|
795
|
+
var canvasGradient = canvasContext.createLinearGradient(
|
|
741
796
|
rect.origin.x + gradient.start.x * rect.size.width,
|
|
742
797
|
rect.origin.y + gradient.start.y * rect.size.height,
|
|
743
798
|
rect.origin.x + gradient.end.x * rect.size.width,
|
|
@@ -748,14 +803,10 @@ JSClass("UIHTMLDisplayServerCanvasContext", UIHTMLDisplayServerContext, {
|
|
|
748
803
|
stop = gradient.stops[i];
|
|
749
804
|
canvasGradient.addColorStop(stop.position, stop.color.cssString());
|
|
750
805
|
}
|
|
751
|
-
|
|
752
|
-
this.canvasContext.stroke();
|
|
753
|
-
this.canvasContext.restore();
|
|
754
|
-
this.beginPath();
|
|
806
|
+
return canvasGradient;
|
|
755
807
|
},
|
|
756
808
|
|
|
757
|
-
|
|
758
|
-
var rect = path.boundingRect;
|
|
809
|
+
_radialGradientForCanvasContext: function(canvasContext, gradient, rect){
|
|
759
810
|
var r0 = 0;
|
|
760
811
|
var start = JSPoint(
|
|
761
812
|
rect.origin.x + gradient.start.x * rect.size.width,
|
|
@@ -766,9 +817,7 @@ JSClass("UIHTMLDisplayServerCanvasContext", UIHTMLDisplayServerContext, {
|
|
|
766
817
|
rect.origin.y + gradient.end.y * rect.size.height
|
|
767
818
|
);
|
|
768
819
|
var r1 = start.distanceToPoint(end);
|
|
769
|
-
|
|
770
|
-
this.addPath(path);
|
|
771
|
-
var canvasGradient = this.canvasContext.createRadialGradient(
|
|
820
|
+
var canvasGradient = canvasContext.createRadialGradient(
|
|
772
821
|
start.x,
|
|
773
822
|
start.y,
|
|
774
823
|
r0,
|
|
@@ -781,10 +830,7 @@ JSClass("UIHTMLDisplayServerCanvasContext", UIHTMLDisplayServerContext, {
|
|
|
781
830
|
stop = gradient.stops[i];
|
|
782
831
|
canvasGradient.addColorStop(stop.position, stop.color.cssString());
|
|
783
832
|
}
|
|
784
|
-
|
|
785
|
-
this.canvasContext.stroke();
|
|
786
|
-
this.canvasContext.restore();
|
|
787
|
-
this.beginPath();
|
|
833
|
+
return canvasGradient;
|
|
788
834
|
},
|
|
789
835
|
|
|
790
836
|
// ----------------------------------------------------------------------
|
|
@@ -917,6 +963,45 @@ JSClass("UIHTMLDisplayServerCanvasContext", UIHTMLDisplayServerContext, {
|
|
|
917
963
|
}
|
|
918
964
|
},
|
|
919
965
|
|
|
966
|
+
// ----------------------------------------------------------------------
|
|
967
|
+
// MARK: - Transparency Layers
|
|
968
|
+
|
|
969
|
+
_reusableTransparencyLayer: null,
|
|
970
|
+
|
|
971
|
+
createTransparencyLayer: function(){
|
|
972
|
+
var scale = this.deviceScale * this.renderScale;
|
|
973
|
+
if (this._reusableTransparencyLayer !== null){
|
|
974
|
+
layer = this._reusableTransparencyLayer;
|
|
975
|
+
this._reusableTransparencyLayer = null;
|
|
976
|
+
layer.context.resetTransform();
|
|
977
|
+
layer.context.clearRect(0, 0, layer.canvas.width, layer.canvas.height);
|
|
978
|
+
this._canvasContextAdoptState(layer.context, this.state, scale);
|
|
979
|
+
layer.parentContext = this.canvasContext;
|
|
980
|
+
this._canvasContext = layer.context;
|
|
981
|
+
return layer;
|
|
982
|
+
}
|
|
983
|
+
var parentContext = this.canvasContext;
|
|
984
|
+
var canvas = this._canvasElements[0].ownerDocument.createElement("canvas");
|
|
985
|
+
canvas.width = this._canvasElements[0].width;
|
|
986
|
+
canvas.height = this._canvasElements[0].height;
|
|
987
|
+
var context = canvas.getContext("2d");
|
|
988
|
+
this._canvasContextAdoptState(context, this.state, scale);
|
|
989
|
+
var layer = {
|
|
990
|
+
canvas: canvas,
|
|
991
|
+
context: context,
|
|
992
|
+
parentContext: parentContext
|
|
993
|
+
};
|
|
994
|
+
this._canvasContext = context;
|
|
995
|
+
return layer;
|
|
996
|
+
},
|
|
997
|
+
|
|
998
|
+
drawTransparencyLayer: function(transparencyLayer){
|
|
999
|
+
this._canvasContext = transparencyLayer.parentContext;
|
|
1000
|
+
this._canvasContext.resetTransform();
|
|
1001
|
+
this._canvasContext.drawImage(transparencyLayer.canvas, 0, 0);
|
|
1002
|
+
this._reusableTransparencyLayer = transparencyLayer;
|
|
1003
|
+
},
|
|
1004
|
+
|
|
920
1005
|
// ----------------------------------------------------------------------
|
|
921
1006
|
// MARK: - Clipping
|
|
922
1007
|
|
|
@@ -1296,29 +1381,25 @@ JSClass("UIHTMLDisplayServerCanvasContextPath", JSPath, {
|
|
|
1296
1381
|
canvasOperations: function(prototype, transform){
|
|
1297
1382
|
var operations = [];
|
|
1298
1383
|
var i, l;
|
|
1299
|
-
var
|
|
1300
|
-
var
|
|
1301
|
-
var segment;
|
|
1384
|
+
var elements = this.elements;
|
|
1385
|
+
var element;
|
|
1302
1386
|
var point;
|
|
1303
1387
|
var cp1;
|
|
1304
1388
|
var cp2;
|
|
1305
|
-
for (i = 0, l =
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
}
|
|
1320
|
-
}
|
|
1321
|
-
if (subpath.closed){
|
|
1389
|
+
for (i = 0, l = elements.length; i < l; ++i){
|
|
1390
|
+
element = elements[i];
|
|
1391
|
+
if (element.type === JSPathElement.Type.move){
|
|
1392
|
+
point = transform.convertPointToTransform(element.point);
|
|
1393
|
+
operations.push({method: prototype.moveTo, arguments: [point.x, point.y]});
|
|
1394
|
+
}else if (element.type === JSPathElement.Type.line){
|
|
1395
|
+
point = transform.convertPointToTransform(element.point);
|
|
1396
|
+
operations.push({method: prototype.lineTo, arguments: [point.x, point.y]});
|
|
1397
|
+
}else if (element.type === JSPathElement.Type.cubicCurve){
|
|
1398
|
+
point = transform.convertPointToTransform(element.curve.p2);
|
|
1399
|
+
cp1 = transform.convertPointToTransform(element.curve.cp1);
|
|
1400
|
+
cp2 = transform.convertPointToTransform(element.curve.cp2);
|
|
1401
|
+
operations.push({method: prototype.bezierCurveTo, arguments: [cp1.x, cp1.y, cp2.x, cp2.y, point.x, point.y]});
|
|
1402
|
+
}else if (element.type === JSPathElement.Type.close){
|
|
1322
1403
|
operations.push({method: prototype.closePath, arguments: []});
|
|
1323
1404
|
}
|
|
1324
1405
|
}
|
|
@@ -99,6 +99,11 @@ JSClass("UIHTMLTextRun", JSTextRun, {
|
|
|
99
99
|
context.translateBy(point.x, point.y + this.font.ascender);
|
|
100
100
|
context.setFont(this.font);
|
|
101
101
|
context.setFillColor(this.attributes.textColor);
|
|
102
|
+
if (this.attributes.strokeWidth){
|
|
103
|
+
context.setLineWidth(this.attributes.strokeWidth);
|
|
104
|
+
context.setStrokeColor(this.attributes.strokeColor);
|
|
105
|
+
context.setTextDrawingMode(JSContext.TextDrawingMode.fillStroke);
|
|
106
|
+
}
|
|
102
107
|
context.showText(this.textNode.nodeValue);
|
|
103
108
|
context.restore();
|
|
104
109
|
}
|
|
@@ -37,6 +37,7 @@ JSClass("UIHTMLTextTypesetter", JSTextTypesetter, {
|
|
|
37
37
|
this._lineElementQueue = [];
|
|
38
38
|
},
|
|
39
39
|
|
|
40
|
+
_useCanvasMetricsForMeasure: true,
|
|
40
41
|
_suggestedHTMLLineLayout: null,
|
|
41
42
|
|
|
42
43
|
canvasContext: null,
|
|
@@ -204,6 +205,14 @@ JSClass("UIHTMLTextTypesetter", JSTextTypesetter, {
|
|
|
204
205
|
span.style.color = textColor ? textColor.cssString() : 'black';
|
|
205
206
|
span.style.backgroundColor = backgroundColor ? backgroundColor.cssString() : '';
|
|
206
207
|
span.style.pointerEvents = 'none';
|
|
208
|
+
|
|
209
|
+
// Stroke
|
|
210
|
+
var strokeColor = attributes[JSAttributedString.Attribute.strokeColor] || null;
|
|
211
|
+
var strokeWidth = attributes[JSAttributedString.Attribute.strokeWidth] || 0;
|
|
212
|
+
if (strokeWidth > 0){
|
|
213
|
+
span.style.webkitTextStrokeWidth = '%fpx'.sprintf(strokeWidth);
|
|
214
|
+
span.style.webkitTextStrokeColor = strokeColor ? strokeColor.cssString() : 'black';
|
|
215
|
+
}
|
|
207
216
|
},
|
|
208
217
|
|
|
209
218
|
_styleAttachmentElementWithAttributes: function(span, attributes, attachment){
|
|
@@ -260,10 +269,16 @@ JSClass("UIHTMLTextTypesetter", JSTextTypesetter, {
|
|
|
260
269
|
runDescriptor.attachment = attachment;
|
|
261
270
|
}else{
|
|
262
271
|
if (!newline){
|
|
263
|
-
if (
|
|
264
|
-
|
|
272
|
+
if (this._useCanvasMetricsForMeasure){
|
|
273
|
+
if (attributes[JSAttributedString.Attribute.maskCharacter] !== undefined){
|
|
274
|
+
metrics = this.canvasContext.measureText(attributes[JSAttributedString.Attribute.maskCharacter]);
|
|
275
|
+
}else{
|
|
276
|
+
metrics = this.canvasContext.measureText(iterator.utf16);
|
|
277
|
+
}
|
|
265
278
|
}else{
|
|
266
|
-
metrics =
|
|
279
|
+
metrics = {
|
|
280
|
+
width: runDescriptor.font.widthOfString(iterator.utf16)
|
|
281
|
+
};
|
|
267
282
|
}
|
|
268
283
|
usedWidth += metrics.width;
|
|
269
284
|
runDescriptor.userPerceivedCharacterWidths.push(metrics.width);
|
|
@@ -2229,17 +2229,19 @@ JSClass("UIListView", UIScrollView, {
|
|
|
2229
2229
|
|
|
2230
2230
|
_contextSelectCell: function(cell, location){
|
|
2231
2231
|
if (this.delegate && this.delegate.menuForListViewCellAtIndexPath){
|
|
2232
|
+
if (this._selectionContainsIndexPath(cell.indexPath)){
|
|
2233
|
+
this._contextSelectedIndexPaths = JSCopy(this._selectedIndexPaths);
|
|
2234
|
+
}else{
|
|
2235
|
+
this._contextSelectedIndexPaths = [cell.indexPath];
|
|
2236
|
+
}
|
|
2232
2237
|
var menu = this.delegate.menuForListViewCellAtIndexPath(this, cell.indexPath);
|
|
2233
2238
|
if (menu !== null){
|
|
2234
|
-
if (this._selectionContainsIndexPath(cell.indexPath)){
|
|
2235
|
-
this._contextSelectedIndexPaths = JSCopy(this._selectedIndexPaths);
|
|
2236
|
-
}else{
|
|
2237
|
-
this._contextSelectedIndexPaths = [cell.indexPath];
|
|
2238
|
-
}
|
|
2239
2239
|
this._updateVisibleCellStates();
|
|
2240
2240
|
var locationInCell = this.convertPointToView(location, cell);
|
|
2241
2241
|
menu.delegate = this;
|
|
2242
2242
|
menu.openAtLocationInContextView(locationInCell, cell);
|
|
2243
|
+
}else{
|
|
2244
|
+
this._contextSelectedIndexPaths = [];
|
|
2243
2245
|
}
|
|
2244
2246
|
}
|
|
2245
2247
|
},
|
|
@@ -477,6 +477,7 @@ JSClass("UIMenuWindowStyler", UIMenuStyler, {
|
|
|
477
477
|
borderWidth: JSDynamicProperty('_borderWidth', 0.5),
|
|
478
478
|
itemContentInsets: JSDynamicProperty('_itemContentInsets', JSInsets(2, 3, 2, 7)),
|
|
479
479
|
indentationSize: JSDynamicProperty('_indentationSize', 10),
|
|
480
|
+
submenuIndicatorIcon: null,
|
|
480
481
|
separatorSize: 10,
|
|
481
482
|
separatorLineWidth: 1,
|
|
482
483
|
separatorColor: null,
|
|
@@ -490,6 +491,7 @@ JSClass("UIMenuWindowStyler", UIMenuStyler, {
|
|
|
490
491
|
this.shadowColor = JSColor.menuShadow;
|
|
491
492
|
this.shadowOffset = JSPoint.Zero;
|
|
492
493
|
this.separatorColor = this.disabledTextColor;
|
|
494
|
+
this.submenuIndicatorIcon = JSImage.initWithResourceName("UIMenuItemSubmenu", this.bundle).imageWithRenderMode(JSImage.RenderMode.template);
|
|
493
495
|
},
|
|
494
496
|
|
|
495
497
|
initWithSpec: function(spec){
|
|
@@ -552,8 +554,17 @@ JSClass("UIMenuWindowStyler", UIMenuStyler, {
|
|
|
552
554
|
if (spec.containsKey('indentationSize')){
|
|
553
555
|
this.indentationSize = spec.valueForKey("indentationSize", Number);
|
|
554
556
|
}
|
|
557
|
+
if (spec.containsKey('submenuIndicatorIcon')){
|
|
558
|
+
this.submenuIndicatorIcon = spec.valueForKey("submenuIndicatorIcon", Number);
|
|
559
|
+
}else{
|
|
560
|
+
this.submenuIndicatorIcon = JSImage.initWithResourceName("UIMenuItemSubmenu", this.bundle).imageWithRenderMode(JSImage.RenderMode.template);
|
|
561
|
+
}
|
|
555
562
|
},
|
|
556
563
|
|
|
564
|
+
bundle: JSLazyInitProperty(function(){
|
|
565
|
+
return JSBundle.initWithIdentifier("io.breakside.JSKit.UIKit");
|
|
566
|
+
}),
|
|
567
|
+
|
|
557
568
|
presentMenuAdjacentToView: function(menu, view, preferredPlacement, spacing){
|
|
558
569
|
if (preferredPlacement === undefined){
|
|
559
570
|
preferredPlacement = UIMenu.Placement.below;
|
|
@@ -857,46 +868,47 @@ JSClass("UIMenuWindowStyler", UIMenuStyler, {
|
|
|
857
868
|
invalidateMenuPresentation: function(menu){
|
|
858
869
|
var window = menu.stylerProperties.window || null;
|
|
859
870
|
if (window !== null && window.screen !== null){
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
var screenMetrics = this.metricsForScreen(window.screen);
|
|
864
|
-
var size = JSSize(window.frame.size);
|
|
871
|
+
window.invalidate();
|
|
872
|
+
}
|
|
873
|
+
},
|
|
865
874
|
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
}
|
|
875
|
+
repositionWindow: function(window){
|
|
876
|
+
var menu = window._menu;
|
|
877
|
+
var screenMetrics = this.metricsForScreen(window.screen);
|
|
878
|
+
var size = JSSize(window.frame.size);
|
|
871
879
|
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
880
|
+
// Ensure we're at least the minimum width
|
|
881
|
+
// (although max width will take precedence)
|
|
882
|
+
if (size.width < menu._minimumWidth){
|
|
883
|
+
size.width = menu._minimumWidth;
|
|
884
|
+
}
|
|
876
885
|
|
|
877
|
-
|
|
878
|
-
|
|
886
|
+
// Limit width to the max screen width
|
|
887
|
+
if (size.width > screenMetrics.maximumWidth){
|
|
888
|
+
size.width = screenMetrics.maximumWidth;
|
|
889
|
+
}
|
|
879
890
|
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
if (over > 0){
|
|
883
|
-
origin.x -= over;
|
|
884
|
-
}
|
|
885
|
-
if (origin.x < screenMetrics.safeFrame.origin.x){
|
|
886
|
-
origin.x = screenMetrics.safeFrame.origin.x;
|
|
887
|
-
}
|
|
891
|
+
// Set our origin so the origin of the target item matches the given location
|
|
892
|
+
var origin = JSPoint(window.frame.origin);
|
|
888
893
|
|
|
889
|
-
|
|
894
|
+
// Adjust our x position if we've overflowed
|
|
895
|
+
var over = origin.x + size.width - screenMetrics.safeFrame.origin.x - screenMetrics.safeFrame.size.width;
|
|
896
|
+
if (over > 0){
|
|
897
|
+
origin.x -= over;
|
|
898
|
+
}
|
|
899
|
+
if (origin.x < screenMetrics.safeFrame.origin.x){
|
|
900
|
+
origin.x = screenMetrics.safeFrame.origin.x;
|
|
901
|
+
}
|
|
890
902
|
|
|
891
|
-
|
|
892
|
-
over = origin.y + size.height - screenMetrics.safeFrame.origin.y - screenMetrics.safeFrame.size.height;
|
|
893
|
-
if (over > 0){
|
|
894
|
-
size.height -= over;
|
|
895
|
-
}
|
|
903
|
+
var offset = JSPoint.Zero;
|
|
896
904
|
|
|
897
|
-
|
|
898
|
-
|
|
905
|
+
// If we extend beyond the bottom, adjust our height
|
|
906
|
+
over = origin.y + size.height - screenMetrics.safeFrame.origin.y - screenMetrics.safeFrame.size.height;
|
|
907
|
+
if (over > 0){
|
|
908
|
+
size.height -= over;
|
|
899
909
|
}
|
|
910
|
+
|
|
911
|
+
window.frame = JSRect(origin, size);
|
|
900
912
|
},
|
|
901
913
|
|
|
902
914
|
metricsForScreen: function(screen){
|
|
@@ -1009,6 +1021,12 @@ UIMenu.keyEquivalentCodeForKeyCode = function(keyCode){
|
|
|
1009
1021
|
case 0xBD:
|
|
1010
1022
|
characterCode = 0x2D; // -
|
|
1011
1023
|
break;
|
|
1024
|
+
case 0xDB:
|
|
1025
|
+
characterCode = 0x5B; // [
|
|
1026
|
+
break;
|
|
1027
|
+
case 0xDD:
|
|
1028
|
+
characterCode = 0x5D; // [
|
|
1029
|
+
break;
|
|
1012
1030
|
}
|
|
1013
1031
|
}
|
|
1014
1032
|
return UIMenu.keyEquivalentCodeForCharacterCode(characterCode);
|