Compare commits

...
Author SHA1 Message Date
NotAlexNoyleandClaude Fable 5.1 db070f0003 addons: an add-on naming both the AppCompat GUID and the toolkit is matched by the entry that fits
matchingTargetApplication prefers, in order: this application's own id, the
AppCompat GUID (extensions.guid.appCompatId, the Firefox GUID), the toolkit.
The AppCompat entry was taken whenever present, whatever its version range.

An add-on can name both for different reasons: the GUID entry for the
application that owns that GUID, at that application's versions (Basilisk is
{ec8030f7-...} at 52.9.x), and a toolkit entry meaning "any other application
on this platform". For an application that is neither, with an AppCompat
version of 56.9, the GUID entry "52.9.0 - 52.9.*" under strict compatibility
does not fit - and because it was preferred, the toolkit entry that does
describe the application was never looked at. The add-on was installed and
immediately disabled as incompatible.

Now the AppCompat entry is used only if it admits the AppCompat version (both
bounds under strict compatibility, the lower bound otherwise - the rule
isCompatibleWith applies) or if there is no toolkit entry to fall back to.
Nothing changes for an add-on that names one of the two, or whose GUID entry
fits.

Found with Palefill 1.30 (toolkit@mozilla.org 4.8.2 - 10.*, platform 6.9.0),
which now installs enabled and applies its fixes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LcrVQFRMC2ANGDfVaRG9Ed
2026-10-05 18:11:17 -04:00
NotAlexNoyleandClaude Fable 5.1 628ee50c99 plugin-container: do not hand the bundled library path to what the plugin runs
The plugin child is started through the bundled loader with an explicit
--library-path, which is what its own dlopen()s search; the LD_LIBRARY_PATH it
also inherits is not needed by it, but is inherited again by anything the
plugin spawns. Flash for Linux runs sh -c "ps x | grep netscape" at start-up:
the device's own /bin/sh (glibc 2.8) then loaded the bundled glibc 2.23 and
died with SIGSEGV, leaving a crash report for every page with Flash on it.

Unset it at child start-up, only when the bundled loader is in use
(MOZ_CHILD_PROCESS_LOADER), so a desktop build keeps its environment.

On the device: a Flash page loads and plays, and no report is written.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LcrVQFRMC2ANGDfVaRG9Ed
2026-10-05 15:46:38 -04:00
NotAlexNoyleandClaude Fable 5.1 0048d50fa9 plugins: an instance with no window to be given is windowless, not a null dereference
nsPluginInstanceOwner::CreateWidget() creates a child-window widget for a
windowed plugin and then calls Create() on it without checking that the widget
exists. A build with no child-window widget (the offscreen embedding registers
none for kWidgetCID) got null back and crashed with SIGSEGV on every page whose
Flash movie was embedded the ordinary way: a plugin is windowed unless it asks
otherwise, and Flash asks only for wmode=opaque or transparent.

With no widget to create, mark the instance windowless and carry on down the
windowless path. That is what webOS's own browser did - it had no plugin
windows and handed every plugin a drawable - and the webOS Flash build draws
through the Palm window structure in both modes.

Found on the device: two "Flash test" pages reached from a search results page
killed the daemon in a loop (the card reconnects and reopens the address).
After the change both render their movies and the daemon keeps its PID.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LcrVQFRMC2ANGDfVaRG9Ed
2026-10-05 15:30:05 -04:00
NotAlexNoyle 9dedcd5fe5 extensions: a link or navigation to an .xpi must reach the install flow in a chrome-less embedding
amContentHandler cancels the load and then hands the install to either a
chrome-privileged frameElement above the page or the content frame message
manager. This embedding has neither, so the hand-off threw after the load had
already been cancelled: following a plain link to an .xpi, or typing its
address, did nothing — no prompt, no error. InstallTrigger.install() was fixed
the same way earlier; call the add-ons integration service directly here too.
2026-10-01 13:22:49 -04:00
NotAlexNoyle 1fff802335 gfx: BasicPlanarYCbCrImage::CopyData must not report failure under delayed conversion
BasicImageLayer::Paint swaps the BasicLayerManager's image factory into the
video ImageContainer for the duration of a paint. A decoder thread that calls
CreatePlanarYCbCrImage() inside that window gets a BasicPlanarYCbCrImage, and
VideoData::SetVideoDataToImage always requests delayed conversion before
CopyData(). CopyData copied the planes and then returned false, so
CreateAndCopyData returned null and the decoder reported
NS_ERROR_OUT_OF_MEMORY -> MEDIA_ERR_DECODE.

With OMTC off a software paint on the TouchPad takes 40-160 ms, so a decode
landed in the window within the first 10-60 frames of every clip.

Return the base copy's result, and true when conversion is delayed: the
image is fully usable, GetAsSourceSurface() converts on demand.
2026-10-01 09:12:50 -04:00
NotAlexNoyleandClaude Opus 4.8 bd49435b11 cubeb: classify media streams + export a playing-stream count for the daemon
Set media.role=music by default (tunable/disable via $JIHAD_STATE_DIR/pulse.props) so the
stream takes the webOS media-policy path (pmedia), and maintain an exported
jihad_pulse_active_streams() count (visibility(default), like MOZ_EXPORT) that the daemon polls
to hold the audiod media scenario + force the speaker route while audio plays. Per-stream flag
inc/dec on play/stop/destroy; calloc zero-inits it. UNVERIFIED by ear — see impl-audio-backend.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-17 10:15:19 -04:00
NotAlexNoyleandClaude Opus 4.8 81e10aa37e videocontrols: surface media errors for audio-only content
setupStatusFader hid the status overlay for isAudioOnly unconditionally, which also hid
the ERROR state — so an <audio> whose format cannot be decoded (MP3/AAC have no decoder
in this build; err=4 MEDIA_ERR_SRC_NOT_SUPPORTED) rendered a live-looking control bar with
no failure shown (the forbidden works-looking-but-silent shape, gre-widgets R1). Keep the
throbber/loading suppression but let a genuine, non-suppressed video.error surface for
audio-only too. Normal decodable audio is untouched. Device-verified: MP3 <audio> now shows
the X + 'format is not supported' overlay.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-17 08:12:56 -04:00
NotAlexNoyleandClaude Opus 4.8 0c10df5c94 videocontrols: fix scrubber flicker/settle + interpolate the thumb
On the offscreen webOS surface the media-controls scrubber had three defects, all fixed
here (the flicker root cause was the daemon's per-buffer damage, fixed separately):

- showDuration ran every timeupdate, re-setting scrubber.max (relayout) and the thumb's
  showhours attr (restyle) each tick -> jitter + a flashing time bubble. Dedup on the
  finite duration so it runs once.
- 'ended' snapped the thumb to the throttled currentTime, a few ms short of the end, so it
  never came to rest at the clip end. Snap to duration for finite durations.
- timeupdate fires ~4x/sec, so the thumb stepped forward in visible jumps. A 40ms interval
  (25fps) drives the thumb position from the live currentTime clock while playing. 40ms is
  the ceiling: 25ms/40fps overruns the adapter's composite-and-return round-trip and stalls
  (checked against Atlas BrowserServer, which uses the same double-buffer + wait-for-return
  flow control with fewer buffers). Only nudges scrubber.value; duration stays owned by the
  event path; guarded on a known finite duration so it never runs before metadata.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-16 10:05:39 -04:00
NotAlexNoyleandClaude Opus 4.8 07259a27f0 Jihad engine mods: NPAPI/webOS plugin host, offscreen PuppetWidget, headless toolkit, pulse cubeb, PmLog sem shim
Vendored delta on pristine UXP b2594a4 (upstream master). Captures the full
jihad engine patch set as a durable commit so the OE bitbake clone builds the
exact source the desktop host build compiles, instead of a stale patch queue
that no longer applies to pristine UXP.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-16 08:35:50 -04:00
Moonchild b2594a4ace Merge pull request 'Revert gtk file dialog change and set default to cancel' (#3137) from 3136 into master
Reviewed-on: https://repo.palemoon.org/MoonchildProductions/UXP/pulls/3137
2026-06-30 13:54:19 +00:00
Moonchild ce61835a81 revert 8a2a9ead92
revert [gtk] Default the file dialog operation to cancelling the operation.

While this could be an annoying default for users expecting fast-track
dialog operations with hitting enter, it avoids potential social
engineering attacks and unintended file operations.
2026-06-30 13:53:18 +00:00
Moonchild 30e29845c4 Merge pull request 'Decouple NPAPI from GTK2' (#3133) from Basilisk-Dev/UXP-contrib:npapi-no-gtk2 into master
Reviewed-on: https://repo.palemoon.org/MoonchildProductions/UXP/pulls/3133
2026-06-30 13:51:11 +00:00
Basilisk-Dev d8662c5dd9 Issue #3132 - use ENABLE check for npapi gtk2 builds instead of a dedicated DISABLE check to match other config options 2026-06-30 09:15:45 -04:00
Moonchild 8a2a9ead92 [gtk] Default the file dialog operation to cancelling the operation.
While this could be an annoying default for users expecting fast-track
dialog operations with hitting enter, it avoids potential social
engineering attacks and unintended file operations.
2026-06-28 12:09:07 +02:00
Moonchild efdbd34b0b Revert "Bug 2033848 - Use non-default response ID for GTK file picker accept button. r=stransky"
This reverts commit 789e976ace.
2026-06-28 12:08:59 +02:00
Moonchild d2fa69f593 Merge pull request 'Import missing libpng files for loongarch and plug them into moz.build' (#3135) from Basilisk-Dev/UXP-contrib:png-loongarch-fix into master
Reviewed-on: https://repo.palemoon.org/MoonchildProductions/UXP/pulls/3135
2026-06-27 07:25:51 +00:00
Basilisk-Dev 18d0a1a525 Issue #3134 - Import missing libpng files for loongarch and plug them into moz.build 2026-06-26 14:48:51 -04:00
Basilisk-Dev 0a5e50a9fe Issue #3132 - Resolve GTK3 ATK bridge dynamically 2026-06-26 13:49:15 -04:00
Basilisk-Dev 3f5b7ed020 Issue #3132 - Add GTK2 NPAPI build toggle 2026-06-26 13:09:49 -04:00
Moonchild 9d9802c660 Issue #3129 - Follow-up: Add aarch64 to platforms enabling Neon in libpng. 2026-06-26 16:58:21 +02:00
Moonchild 27c579652a Issue #3122 - Stop using <base> element in json viewer.
Resolves #3122
2026-06-23 21:09:02 +02:00
Moonchild 8ffa6b3c13 Issue #3129 - Add palette_neon_intrinsics.c to moz.build 2026-06-23 10:23:17 +02:00
Moonchild 83f6efc33d Issue #3122 - Put base paths in the json viewer client deps.
The dependency modules are requested early. Seems CSP can block baseURL
on these networking requests, so add the base manually to the resource
paths to prevent network requests before the html base element is
resolved and active.
2026-06-22 17:58:21 +02:00
Moonchild 47f1928610 Merge pull request 'Libpng update 1.6.58' (#3125) from libpng-update-1.6.58 into master
Reviewed-on: https://repo.palemoon.org/MoonchildProductions/UXP/pulls/3125
2026-06-21 12:14:42 +00:00
Moonchild 7b3d961465 Bump NSS version for adopted changes. 2026-06-19 14:19:43 +02:00
Moonchild 22b2e18d91 [DOM] Clean up WebGL transform feedback validation. 2026-06-19 13:30:35 +02:00
John Schanck f6c9c0c59f Bug 2030564 - add defensive input validation to sftk_compute_ANSI_X9_63_kdf. 2026-06-19 12:56:26 +02:00
John Schanck d8c9d24a9c Bug 2030366 - avoid race with module unloading in NSSTrustDomain_FindTokensByURI. 2026-06-19 12:04:23 +02:00
John Schanck a466b73267 Bug 2029403 - avoid PORT_Strdup in ssl_DecodeResumptionToken. 2026-06-19 10:51:37 +02:00
Julian Descottes 1ce14fb014 [devtools] Consistently show filepicker on first save action from StyleEditor.
Bug 2038133
2026-06-19 10:45:33 +02:00
Moonchild 8bbf60fb38 Issue #3127 - Add trademark notice to the tree.
Resolves #3127
2026-06-19 08:37:27 +02:00
Moonchild f2d7c02290 Apply (hopefully for the last time before 2.0.x) APNG support code.
This commit also removes MOZCHANGES (old and irrelevant information)
This commit also adds a new readme.
2026-06-18 22:57:29 +02:00
Moonchild 65ddfc21b6 Fresh import of libpng 1.6.58 2026-06-18 21:50:35 +02:00
Moonchild 163619de60 [network] Make HttpBaseChannel::mLoadFlags atomic. 2026-06-18 20:32:03 +02:00
Moonchild 29c4d554a0 [gfx] Check more offsets during CFF subsetting.
Also fixes a bunch of whitespace (TAB -> spaces)
2026-06-18 19:35:49 +02:00
Moonchild 3e59569d0b [DOM] Avoid over-optimizing some getter/function calls. 2026-06-18 13:45:20 +02:00
Moonchild fb8483407b [parser] Better align with spec definition of adding nodes. 2026-06-18 13:32:16 +02:00
Moonchild ec8b7f86d0 No issue - Use ImmGCPtr for module meta data visits.
This should make module GCs less touchy.
2026-06-17 23:46:18 +02:00
Moonchild 9899d59010 [DOM media] Zero-initialize ThreadSharedFloatArrayBufferList. 2026-06-17 18:13:15 +02:00
Kui-Feng Lee 789e976ace Bug 2033848 - Use non-default response ID for GTK file picker accept button. r=stransky
Replace GTK_RESPONSE_ACCEPT (-3) with a non-negative application-defined
response ID (kFilePickerAccept = 0) for the accept button in the GTK file
chooser dialog, and remove the gtk_dialog_set_default_response() call.

GTK treats buttons with negative built-in response IDs as candidates for
the dialog's default widget, which activates on Enter key press. By using
a non-negative ID and not calling set_default_response(), the accept button
is no longer pre-selected, preventing a page from tricking the user into
confirming a file upload by holding Enter before the dialog appears.

GTK's file chooser internally emits GTK_RESPONSE_ACCEPT via file_activated_cb
when the user double-clicks a file, so we keep that case in DoneNonPortal()
alongside kFilePickerAccept.
2026-06-17 12:47:03 +02:00
John Schanck d5bf2555a3 Bug 2023478 - improve handling of escape sequences in pk11uri_ParseAttributes. 2026-06-17 12:17:06 +02:00
Moonchild be672813f6 [DOM] Reject too large mLength in MutableBlobStorage::WriteRunnable. 2026-06-16 20:06:25 +02:00
John Schanck 746a7be08c Bug 2030570 - use correct data for ID comparison in transfer_uri_certs_to_collection. 2026-06-16 19:54:44 +02:00
Moonchild c222ee80fa [network] Make keep-alive pref Atomic. 2026-06-16 19:50:55 +02:00
John Schanck 4950bd038d Bug 2029765 - avoid refcount over-release in nssTokenObjectCache error path [@ nssToken_Destroy]. 2026-06-16 18:52:25 +02:00
Nicolas B. Pierron 058336a071 Bug 2029066 - Remove Sinking of Live instructions.
Instruction sinking was made possible by the introduction of recover
instructions, which are moving instructions to be executed on bailout, but this
is only possible for instructions which are not used.

This feature, which is now removed, was made to sink instructions which are
live, but only in a small set of branches, by moving the computation of these
instructions to bailout paths, and to the concerned if branches.

The current implementation never delivered and remained as dead-code for
multiple years, without having a firm benefit on performance oriented
benchmarks.

Thus, this change removes the part of the Sink optimization which deals with
live instructions but keeps the part of the Sink optimization which deals with
instructions which are only used on bailout paths.
2026-06-16 13:37:21 +02:00
John Schanck 6823388a85 Bug 2029803 - add defensive info->len check in PK11_HPKE_SetupS and PK11_HPKE_SetupR. 2026-06-16 09:27:28 +02:00
Moonchild b68d097eb6 Issue #3122 - Exclude local resources from <base> CSP checks.
This avoids local-resource <base> URLs being restricted/nullified by
remote CSP. This aligns the CSP handling with direct requests.

Resolves #3122
2026-06-14 10:08:17 +02:00
161 changed files with 15830 additions and 8257 deletions

No files matched your search

+8
View File
@@ -0,0 +1,8 @@
TRADEMARK NOTICE
================
The name "Goanna" and visual representations (logo) have not been
registered by the Copyright owners as a trademark in any jurisdiction.
However, because Goanna has been distributed and maintained world-wide,
continually since 2015, the Copyright owners claim "common-law trademark
protection" in any jurisdiction where common-law trademark is recognized.
+48 -7
View File
@@ -18,10 +18,6 @@
#endif
#include <gtk/gtk.h>
#if (MOZ_WIDGET_GTK == 3)
extern "C" __attribute__((weak,visibility("default"))) int atk_bridge_adaptor_init(int*, char **[]);
#endif
using namespace mozilla;
using namespace mozilla::a11y;
@@ -33,12 +29,20 @@ extern "C" {
typedef GType (* AtkGetTypeType) (void);
typedef void (*GnomeAccessibilityInit) (void);
typedef void (*GnomeAccessibilityShutdown) (void);
#if (MOZ_WIDGET_GTK == 3)
typedef int (*AtkBridgeAdaptorInit) (int*, char***);
#endif
}
static PRLibrary* sATKLib = nullptr;
static const char sATKLibName[] = "libatk-1.0.so.0";
static const char sATKHyperlinkImplGetTypeSymbol[] =
"atk_hyperlink_impl_get_type";
#if (MOZ_WIDGET_GTK == 3)
static PRLibrary* sAtkBridgeAdaptorLib = nullptr;
static const char sAtkBridgeAdaptorLibName[] = "libatk-bridge-2.0.so.0";
static const char sAtkBridgeAdaptorInitSymbol[] = "atk_bridge_adaptor_init";
#endif
gboolean toplevel_event_watcher(GSignalInvocationHint*, guint, const GValue*,
gpointer);
@@ -127,6 +131,38 @@ LoadGtkModule(GnomeAccessibilityModule& aModule)
return NS_OK;
}
#if (MOZ_WIDGET_GTK == 3)
static bool
InitAtkBridgeAdaptor()
{
AtkBridgeAdaptorInit initBridge =
reinterpret_cast<AtkBridgeAdaptorInit>(
PR_FindFunctionSymbolAndLibrary(sAtkBridgeAdaptorInitSymbol,
&sAtkBridgeAdaptorLib));
if (!initBridge) {
sAtkBridgeAdaptorLib = PR_LoadLibrary(sAtkBridgeAdaptorLibName);
if (sAtkBridgeAdaptorLib) {
initBridge =
reinterpret_cast<AtkBridgeAdaptorInit>(
PR_FindFunctionSymbol(sAtkBridgeAdaptorLib,
sAtkBridgeAdaptorInitSymbol));
if (!initBridge) {
PR_UnloadLibrary(sAtkBridgeAdaptorLib);
sAtkBridgeAdaptorLib = nullptr;
}
}
}
if (!initBridge) {
return false;
}
initBridge(nullptr, nullptr);
return true;
}
#endif
void
a11y::PlatformInit()
{
@@ -181,9 +217,7 @@ a11y::PlatformInit()
// Init atk-bridge now
PR_SetEnv("NO_AT_BRIDGE=0");
#if (MOZ_WIDGET_GTK == 3)
if (atk_bridge_adaptor_init) {
atk_bridge_adaptor_init(nullptr, nullptr);
} else
if (!InitAtkBridgeAdaptor())
#endif
{
nsresult rv = LoadGtkModule(sAtkBridge);
@@ -228,6 +262,13 @@ a11y::PlatformShutdown()
sAtkBridge.init = nullptr;
sAtkBridge.shutdown = nullptr;
}
#if (MOZ_WIDGET_GTK == 3)
if (sAtkBridgeAdaptorLib) {
// Do not shutdown/unload atk-bridge; an exit function registered by
// the bridge will take care of it.
sAtkBridgeAdaptorLib = nullptr;
}
#endif
#if (MOZ_WIDGET_GTK == 2)
if (sGail.lib) {
// Do not shutdown gail because
+1
View File
@@ -164,6 +164,7 @@ def old_configure_options(*options):
'--enable-negotiateauth',
'--enable-nfc',
'--enable-npapi',
'--enable-npapi-gtk2',
'--enable-nspr-build',
'--enable-official-branding',
'--enable-official-vendor',
+5
View File
@@ -88,6 +88,11 @@ check_and_add_gcc_warning('-Wno-error=deprecated-declarations')
# false positives depending on optimization
check_and_add_gcc_warning('-Wno-error=array-bounds')
# GCC 9+ value-range analysis trips -Wformat-overflow on null %s args in debug
# spew (e.g. js/src/jit/x64/BaseAssembler-x64.h:595); harmless for our build,
# and js/src forces -Werror=format so this must be downgraded here to reach it.
check_and_add_gcc_warning('-Wno-error=format-overflow')
# can't get rid of those PGO warnings
check_and_add_gcc_warning('-Wno-error=coverage-mismatch', when='MOZ_PGO')
+7 -6
View File
@@ -204,21 +204,22 @@ function initialHTML(doc) {
os = "linux";
}
let base = doc.createElement("base");
base.href = "resource://devtools/client/jsonview/";
// The appRoot URI is prepended to all URIs instead of using a <base> element
// because the latter can cause spurious network requests (UXP Issue #3122)
let appRoot = "resource://devtools/client/jsonview/";
let style = doc.createElement("link");
style.rel = "stylesheet";
style.type = "text/css";
style.href = "css/main.css";
style.href = appRoot +"css/main.css";
let script = doc.createElement("script");
script.src = "lib/require.js";
script.dataset.main = "viewer-config";
script.src = appRoot + "lib/require.js";
script.dataset.main = appRoot + "viewer-config.js";
script.defer = true;
let head = doc.createElement("head");
head.append(base, style, script);
head.append(style, script);
return "<!DOCTYPE html>\n" +
startTag("html", {
@@ -4,6 +4,8 @@ subsuite = devtools
support-files =
array_json.json
array_json.json^headers^
csp_json.json
csp_json.json^headers^
doc_frame_script.js
head.js
invalid_json.json
@@ -22,6 +24,7 @@ subsuite = clipboard
subsuite = clipboard
[browser_jsonview_copy_rawdata.js]
subsuite = clipboard
[browser_jsonview_csp_json.js]
[browser_jsonview_filter.js]
[browser_jsonview_invalid_json.js]
[browser_jsonview_valid_json.js]
@@ -0,0 +1,17 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const TEST_JSON_URL = URL_ROOT + "csp_json.json";
add_task(function* () {
info("Test CSP JSON started");
yield addJsonViewTab(TEST_JSON_URL);
let count = yield getElementCount(".jsonPanelBox .treeTable .treeRow");
is(count, 1, "There must be one row");
});
@@ -0,0 +1 @@
{"csp": true}
@@ -0,0 +1,2 @@
Content-Type: application/json
Content-Security-Policy: default-src 'none'; base-uri 'none';
+1 -1
View File
@@ -23,7 +23,7 @@
* of the code base, so it's consistent and modules can be easily reused.
*/
require.config({
baseUrl: ".",
baseUrl: "resource://devtools/client/jsonview/",
paths: {
"devtools/client/shared": "resource://devtools/client/shared",
"devtools/shared": "resource://devtools/shared",
@@ -103,12 +103,6 @@ function StyleSheetEditor(styleSheet, win, file, isNew, walker, highlighter) {
}
};
this._styleSheetFilePath = null;
if (styleSheet.href &&
Services.io.extractScheme(this.styleSheet.href) == "file") {
this._styleSheetFilePath = this.styleSheet.href;
}
this._onPropertyChange = this._onPropertyChange.bind(this);
this._onError = this._onError.bind(this);
this._onMediaRuleMatchesChange = this._onMediaRuleMatchesChange.bind(this);
@@ -664,8 +658,7 @@ StyleSheetEditor.prototype = {
if (this._friendlyName) {
defaultName = OS.Path.basename(this._friendlyName);
}
showFilePicker(file || this._styleSheetFilePath, true, this._window,
onFile, defaultName);
showFilePicker(file, true, this._window, onFile, defaultName);
},
/**
@@ -1,98 +1,112 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that 'Save' function works.
const TESTCASE_URI_HTML = TEST_BASE_HTTP + "simple.html";
const TESTCASE_URI_CSS = TEST_BASE_HTTP + "simple.css";
var tempScope = {};
Components.utils.import("resource://gre/modules/FileUtils.jsm", tempScope);
Components.utils.import("resource://gre/modules/NetUtil.jsm", tempScope);
var FileUtils = tempScope.FileUtils;
var NetUtil = tempScope.NetUtil;
add_task(function* () {
let htmlFile = yield copy(TESTCASE_URI_HTML, "simple.html");
yield copy(TESTCASE_URI_CSS, "simple.css");
let uri = Services.io.newFileURI(htmlFile);
let filePath = uri.resolve("");
let { ui } = yield openStyleEditorForURL(filePath);
let editor = ui.editors[0];
yield editor.getSourceEditor();
info("Editing the style sheet.");
let dirty = editor.sourceEditor.once("dirty-change");
let beginCursor = {line: 0, ch: 0};
editor.sourceEditor.replaceText("DIRTY TEXT", beginCursor, beginCursor);
yield dirty;
is(editor.sourceEditor.isClean(), false, "Editor is dirty.");
ok(editor.summary.classList.contains("unsaved"),
"Star icon is present in the corresponding summary.");
info("Saving the changes.");
dirty = editor.sourceEditor.once("dirty-change");
editor.saveToFile(null, function (file) {
ok(file, "file should get saved directly when using a file:// URI");
});
yield dirty;
is(editor.sourceEditor.isClean(), true, "Editor is clean.");
ok(!editor.summary.classList.contains("unsaved"),
"Star icon is not present in the corresponding summary.");
});
function copy(srcChromeURL, destFileName) {
let deferred = defer();
let destFile = FileUtils.getFile("ProfD", [destFileName]);
write(read(srcChromeURL), destFile, deferred.resolve);
return deferred.promise;
}
function read(srcChromeURL) {
let scriptableStream = Cc["@mozilla.org/scriptableinputstream;1"]
.getService(Ci.nsIScriptableInputStream);
let channel = NetUtil.newChannel({
uri: srcChromeURL,
loadUsingSystemPrincipal: true
});
let input = channel.open2();
scriptableStream.init(input);
let data = "";
while (input.available()) {
data = data.concat(scriptableStream.read(input.available()));
}
scriptableStream.close();
input.close();
return data;
}
function write(data, file, callback) {
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
.createInstance(Ci.nsIScriptableUnicodeConverter);
converter.charset = "UTF-8";
let istream = converter.convertToInputStream(data);
let ostream = FileUtils.openSafeFileOutputStream(file);
NetUtil.asyncCopy(istream, ostream, function (status) {
if (!Components.isSuccessCode(status)) {
info("Couldn't write to " + file.path);
return;
}
callback(file);
});
}
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that 'Save' function works.
const TESTCASE_URI_HTML = TEST_BASE_HTTP + "simple.html";
const TESTCASE_URI_CSS = TEST_BASE_HTTP + "simple.css";
var tempScope = {};
Components.utils.import("resource://gre/modules/FileUtils.jsm", tempScope);
Components.utils.import("resource://gre/modules/NetUtil.jsm", tempScope);
var FileUtils = tempScope.FileUtils;
var NetUtil = tempScope.NetUtil;
add_task(function* () {
let htmlFile = yield copy(TESTCASE_URI_HTML, "simple.html");
const cssFile = await copy(TESTCASE_URI_CSS, "simple.css");
let uri = Services.io.newFileURI(htmlFile);
let filePath = uri.resolve("");
let { ui } = yield openStyleEditorForURL(filePath);
let editor = ui.editors[0];
yield editor.getSourceEditor();
is(
editor.savedFile,
null,
"savedFile should not be pre-populated from the source file"
);
info("Editing the style sheet.");
let dirty = editor.sourceEditor.once("dirty-change");
let beginCursor = {line: 0, ch: 0};
editor.sourceEditor.replaceText("DIRTY TEXT", beginCursor, beginCursor);
yield dirty;
is(editor.sourceEditor.isClean(), false, "Editor is dirty.");
ok(editor.summary.classList.contains("unsaved"),
"Star icon is present in the corresponding summary.");
info(
"Saving the changes with an explicit file (simulating a user-chosen save location)."
);
dirty = editor.sourceEditor.once("dirty-change");
editor.saveToFile(cssFile, function (file) {
ok(file, "file should get saved when explicitly passing a file");
});
yield dirty;
is(editor.sourceEditor.isClean(), true, "Editor is clean.");
ok(!editor.summary.classList.contains("unsaved"),
"Star icon is not present in the corresponding summary.");
is(
editor.savedFile?.path,
cssFile.path,
"savedFile should now be set on the editor"
);
});
function copy(srcChromeURL, destFileName) {
let deferred = defer();
let destFile = FileUtils.getFile("ProfD", [destFileName]);
write(read(srcChromeURL), destFile, deferred.resolve);
return deferred.promise;
}
function read(srcChromeURL) {
let scriptableStream = Cc["@mozilla.org/scriptableinputstream;1"]
.getService(Ci.nsIScriptableInputStream);
let channel = NetUtil.newChannel({
uri: srcChromeURL,
loadUsingSystemPrincipal: true
});
let input = channel.open2();
scriptableStream.init(input);
let data = "";
while (input.available()) {
data = data.concat(scriptableStream.read(input.available()));
}
scriptableStream.close();
input.close();
return data;
}
function write(data, file, callback) {
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
.createInstance(Ci.nsIScriptableUnicodeConverter);
converter.charset = "UTF-8";
let istream = converter.convertToInputStream(data);
let ostream = FileUtils.openSafeFileOutputStream(file);
NetUtil.asyncCopy(istream, ostream, function (status) {
if (!Components.isSuccessCode(status)) {
info("Couldn't write to " + file.path);
return;
}
callback(file);
});
}
@@ -28,7 +28,10 @@ add_task(function* () {
let HTMLFile = yield copy(TESTCASE_URI_HTML, ["sourcemaps.html"]);
let CSSFile = yield copy(TESTCASE_URI_CSS,
["sourcemap-css", "sourcemaps.css"]);
yield copy(TESTCASE_URI_SCSS, ["sourcemap-sass", "sourcemaps.scss"]);
const SCSSFile = await copy(TESTCASE_URI_SCSS, [
"sourcemap-sass",
"sourcemaps.scss",
]);
yield copy(TESTCASE_URI_MAP, ["sourcemap-css", "sourcemaps.css.map"]);
yield copy(TESTCASE_URI_REG_CSS, ["simple.css"]);
@@ -59,7 +62,7 @@ add_task(function* () {
// Edit and save Sass in the editor. This will start off a file-watching
// process waiting for the CSS file to change.
yield editSCSS(editor);
yield editSCSS(SCSSFile, editor);
// We can't run Sass or another compiler, so we fake it by just
// directly changing the CSS file.
@@ -73,12 +76,12 @@ add_task(function* () {
is(color, "rgb(0, 0, 255)", "div is blue after saving file");
});
function editSCSS(editor) {
function editSCSS(SCSSFile, editor) {
let deferred = defer();
editor.sourceEditor.setText(CSS_TEXT);
editor.saveToFile(null, function (file) {
editor.saveToFile(SCSSFile, function (file) {
ok(file, "Scss file should be saved");
deferred.resolve();
});
+1 -1
View File
@@ -52,7 +52,7 @@ static RedirEntry kRedirMap[] = {
{ "config", "chrome://global/content/config.xul", 0 },
{ "console", "chrome://global/content/console.xul", 0 },
{
"credits", "http://www.palemoon.org/Contributors.shtml",
"credits", "https://net.riverstonerelay.jihad-browser/credits",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::MAKE_LINKABLE
},
+28
View File
@@ -199,6 +199,7 @@
#include "nsICommandManager.h"
#include "nsIDOMNode.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIBadCertListener2.h" // JIHAD: route cert errors to the embedder chrome
#include "nsIHttpChannel.h"
#include "nsIIDNService.h"
#include "nsIInputStreamChannel.h"
@@ -1074,6 +1075,33 @@ nsDocShell::GetInterface(const nsIID& aIID, void** aSink)
} else if (aIID.Equals(NS_GET_IID(nsITabChild))) {
*aSink = GetTabChild().take();
return *aSink ? NS_OK : NS_ERROR_FAILURE;
} else if (aIID.Equals(NS_GET_IID(nsIBadCertListener2))) {
// JIHAD: hand the embedder's chrome the certificate error.
//
// NSS asks the channel's notification callbacks for nsIBadCertListener2
// (SSLServerCertVerification.cpp, CertErrorRunnable::CheckCertOverrides) and passes
// it the nsISSLStatus carrying the SERVER CERTIFICATE. That call is the one and only
// place an embedder is handed the cert while it still exists — the same shape the
// Atlas browser gets for free from WebKit's load-failed-with-tls-errors signal, which
// delivers the GTlsCertificate as a signal argument.
//
// Without this hop nothing answers: the docShell's fallthrough is
// nsDocLoader::GetInterface, which Queries the docloader ITSELF, so the request never
// reaches nsIWebBrowserChrome. The embedder is then left trying to recover the cert
// afterwards, and there is no way to: the failed channel's securityInfo has a null
// SSLStatus, and UXP has no nsIRecentBadCerts service. Measured 2026-08-04 — the
// SSL-confirm dialog worked, the user accepted, and the accept could do nothing
// because RememberValidityOverride had no nsIX509Cert to take.
//
// Routed through the tree owner, exactly as nsIWebBrowserChromeFocus and nsIPrompt
// already are (nsDocShellTreeOwner::GetInterface).
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
GetTreeOwner(getter_AddRefs(treeOwner));
nsCOMPtr<nsIInterfaceRequestor> req(do_QueryInterface(treeOwner));
if (req) {
return req->GetInterface(aIID, aSink);
}
return NS_NOINTERFACE;
} else if (aIID.Equals(NS_GET_IID(nsIContentFrameMessageManager))) {
nsCOMPtr<nsITabChild> tabChild =
do_GetInterface(static_cast<nsIDocShell*>(this));
+1 -1
View File
@@ -196,7 +196,7 @@ public:
{
MOZ_ASSERT(!NS_IsMainThread());
int32_t written = PR_Write(mFD, mData, mLength);
int32_t written = mLength < INT32_MAX ? PR_Write(mFD, mData, mLength) : -1;
if (NS_WARN_IF(written < 0 || uint32_t(written) != mLength)) {
return NS_DispatchToMainThread(
new ErrorPropagationRunnable(mBlobStorage, NS_ERROR_FAILURE));
+33 -5
View File
@@ -787,6 +787,12 @@ nsresult
nsObjectLoadingContent::InstantiatePluginInstance(bool aIsLoading)
{
#ifdef MOZ_ENABLE_NPAPI
// JIHAD DIAGNOSTIC (R7): entry + the four early-out conditions. If this line never appears the
// plugin was never asked for at all (no nsPluginFrame -> no HasNewFrame), which is a different
// bug from being asked for and refused.
fprintf(stderr, "[jihad-npapi] InstantiatePluginInstance(aIsLoading=%d) owner=%d type=%d "
"mIsLoading=%d instantiating=%d\n", (int)aIsLoading, (int)!!mInstanceOwner,
(int)mType, (int)mIsLoading, (int)mInstantiating);
if (mInstanceOwner || mType != eType_Plugin || (mIsLoading != aIsLoading) ||
mInstantiating) {
// If we hit this assertion it's probably because LoadObject re-entered :(
@@ -822,10 +828,12 @@ nsObjectLoadingContent::InstantiatePluginInstance(bool aIsLoading)
NS_ENSURE_TRUE(mInstantiating, NS_OK);
if (!thisContent->GetPrimaryFrame()) {
// JIHAD DIAGNOSTIC (R7): a silent NS_OK return — the single most likely place for a plugin
// to "do nothing" with no error anywhere.
fprintf(stderr, "[jihad-npapi] NO PRIMARY FRAME -> not instantiating\n");
LOG(("OBJLC [%p]: Not instantiating plugin with no frame", this));
return NS_OK;
}
nsresult rv = NS_ERROR_FAILURE;
RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
@@ -846,6 +854,8 @@ nsObjectLoadingContent::InstantiatePluginInstance(bool aIsLoading)
rv = pluginHost->InstantiatePluginInstance(mContentType,
mURI.get(), this,
getter_AddRefs(newOwner));
fprintf(stderr, "[jihad-npapi] pluginHost->InstantiatePluginInstance rv=0x%x owner=%d\n",
(unsigned)rv, (int)!!newOwner);
// XXX(johns): We don't suspend native inside stopping plugins...
if (appShell) {
@@ -2378,6 +2388,11 @@ nsObjectLoadingContent::LoadObject(bool aNotify,
FallbackType clickToPlayReason;
if (!mActivated && (mType == eType_Null || mType == eType_Plugin) &&
!ShouldPlay(clickToPlayReason, false)) {
// JIHAD DIAGNOSTIC (R7): this is where a plugin that resolved fine is silently demoted to
// eType_Null. Every path out of ShouldPlay that returns false lands here, so one line here
// names the reason instead of instrumenting each exit.
fprintf(stderr, "[jihad-npapi] demoted to fallback: mType=%d fallbackReason=%d\n",
(int)mType, (int)clickToPlayReason);
LOG(("OBJLC [%p]: Marking plugin as click-to-play", this));
mType = eType_Null;
fallbackType = clickToPlayReason;
@@ -2887,9 +2902,16 @@ nsObjectLoadingContent::GetTypeOfContent(const nsCString& aMIMEType)
#ifdef MOZ_ENABLE_NPAPI
RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
if ((caps & eSupportPlugins) &&
pluginHost &&
pluginHost->HavePluginForType(aMIMEType, nsPluginHost::eExcludeNone)) {
bool jihadHave = pluginHost &&
pluginHost->HavePluginForType(aMIMEType, nsPluginHost::eExcludeNone);
// JIHAD DIAGNOSTIC (R7 windowless port): says, for one MIME type, whether the element
// advertised plugin capability and whether the host has a plugin — the two facts that decide
// if the NPAPI subsystem is entered at all. Added because a plugin that never instantiates
// produces NO plugin logging whatsoever, which is indistinguishable from one that was never
// asked for.
fprintf(stderr, "[jihad-npapi] GetTypeOfContent mime=%s caps=0x%x supportsPlugins=%d have=%d\n",
nsCString(aMIMEType).get(), caps, (int)!!(caps & eSupportPlugins), (int)jihadHave);
if ((caps & eSupportPlugins) && jihadHave) {
// ShouldPlay will handle checking for disabled plugins
return eType_Plugin;
}
@@ -3486,9 +3508,15 @@ nsObjectLoadingContent::ShouldPlay(FallbackType &aReason, bool aIgnoreCurrentTyp
aReason = eFallbackClickToPlay;
uint32_t enabledState = nsIPluginTag::STATE_DISABLED;
pluginHost->GetStateForType(mContentType, nsPluginHost::eExcludeNone,
nsresult jihadStateRv = pluginHost->GetStateForType(mContentType, nsPluginHost::eExcludeNone,
&enabledState);
// JIHAD DIAGNOSTIC (R7): note that enabledState is pre-set to STATE_DISABLED and the rv of
// GetStateForType is NOT checked upstream, so a failing lookup silently blocks the plugin
// with no other trace. Log the rv as well as the value.
fprintf(stderr, "[jihad-npapi] ShouldPlay type=%s enabledState=%u rv=0x%x\n",
mContentType.get(), enabledState, (unsigned)jihadStateRv);
if (nsIPluginTag::STATE_DISABLED == enabledState) {
fprintf(stderr, "[jihad-npapi] ShouldPlay -> FALSE (eFallbackDisabled)\n");
aReason = eFallbackDisabled;
return false;
}
+46 -30
View File
@@ -39,6 +39,44 @@ WebGLTransformFeedback::Delete()
////////////////////////////////////////
// Validation helper for beginning/resuming the TF and computing the
// vertex capacity.
bool
WebGLTransformFeedback::PrepareTransformFeedback() {
const auto& prog = mContext->mCurrentProgram;
if (!prog ||
!prog->IsLinked() ||
!prog->LinkInfo()->componentsPerTFVert.size()) {
mContext->ErrorInvalidOperation("Current program not valid for transform feedback.");
return false;
}
const auto& linkInfo = prog->LinkInfo();
const auto& componentsPerTFVert = linkInfo->componentsPerTFVert;
mActive_VertCapacity = 0;
size_t minVertCapacity = SIZE_MAX;
for (size_t i = 0; i < componentsPerTFVert.size(); i++) {
const auto& indexedBinding = mIndexedBindings[i];
const auto& componentsPerVert = componentsPerTFVert[i];
const auto& buffer = indexedBinding.mBufferBinding;
if (!buffer) {
mContext->ErrorInvalidOperation("No buffer attached to required transform feedback index %u.",
(uint32_t)i);
return false;
}
const size_t vertCapacity = buffer->ByteLength() / 4 / componentsPerVert;
minVertCapacity = std::min(minVertCapacity, vertCapacity);
}
mActive_VertCapacity = minVertCapacity;
return true;
}
void
WebGLTransformFeedback::BeginTransformFeedback(GLenum primMode)
{
@@ -59,37 +97,10 @@ WebGLTransformFeedback::BeginTransformFeedback(GLenum primMode)
return;
}
const auto& prog = mContext->mCurrentProgram;
if (!prog ||
!prog->IsLinked() ||
!prog->LinkInfo()->componentsPerTFVert.size())
{
mContext->ErrorInvalidOperation("%s: Current program not valid for transform"
" feedback.",
funcName);
if (!PrepareTransformFeedback()) {
return;
}
const auto& linkInfo = prog->LinkInfo();
const auto& componentsPerTFVert = linkInfo->componentsPerTFVert;
size_t minVertCapacity = SIZE_MAX;
for (size_t i = 0; i < componentsPerTFVert.size(); i++) {
const auto& indexedBinding = mIndexedBindings[i];
const auto& componentsPerVert = componentsPerTFVert[i];
const auto& buffer = indexedBinding.mBufferBinding;
if (!buffer) {
mContext->ErrorInvalidOperation("%s: No buffer attached to required transform"
" feedback index %u.",
funcName, (uint32_t)i);
return;
}
const size_t vertCapacity = buffer->ByteLength() / 4 / componentsPerVert;
minVertCapacity = std::min(minVertCapacity, vertCapacity);
}
////
const auto& gl = mContext->gl;
@@ -101,10 +112,9 @@ WebGLTransformFeedback::BeginTransformFeedback(GLenum primMode)
mIsActive = true;
MOZ_ASSERT(!mIsPaused);
mActive_Program = prog;
mActive_Program = mContext->mCurrentProgram;
mActive_PrimMode = primMode;
mActive_VertPosition = 0;
mActive_VertCapacity = minVertCapacity;
////
@@ -173,6 +183,12 @@ WebGLTransformFeedback::ResumeTransformFeedback()
return;
}
// Re-run prepare in case some of the buffers have been modified
// while the TF was paused.
if (!PrepareTransformFeedback()) {
return;
}
////
const auto& gl = mContext->gl;
+1
View File
@@ -44,6 +44,7 @@ public:
WebGLTransformFeedback(WebGLContext* webgl, GLuint tf);
private:
~WebGLTransformFeedback();
bool PrepareTransformFeedback();
public:
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTransformFeedback)
+5 -1
View File
@@ -18,6 +18,8 @@
#include "nsContentUtils.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIURI.h"
#include "nsNetUtil.h"
#include "nsIProtocolHandler.h"
NS_IMPL_NS_NEW_HTML_ELEMENT(Shared)
@@ -186,6 +188,8 @@ SetBaseURIUsingFirstBaseWithHref(nsIDocument* aDocument, nsIContent* aMustMatch)
newBaseURI = nullptr;
}
if (csp && newBaseURI) {
bool isLocalResource = false;
rv = NS_URIChainHasFlags(newBaseURI, nsIProtocolHandler::URI_IS_LOCAL_RESOURCE, &isLocalResource);
// base-uri is only enforced if explicitly defined in the
// policy - do *not* consult default-src, see:
// http://www.w3.org/TR/CSP2/#directive-default-src
@@ -193,7 +197,7 @@ SetBaseURIUsingFirstBaseWithHref(nsIDocument* aDocument, nsIContent* aMustMatch)
rv = csp->Permits(newBaseURI, nsIContentSecurityPolicy::BASE_URI_DIRECTIVE,
true /* aSpecific */, true /* aSendViolationReports */,
&cspPermitsBaseURI);
if (NS_FAILED(rv) || !cspPermitsBaseURI) {
if ((NS_FAILED(rv) || !cspPermitsBaseURI) && !isLocalResource) {
newBaseURI = nullptr;
}
}
+1 -1
View File
@@ -26,7 +26,7 @@ ThreadSharedFloatArrayBufferList::Create(uint32_t aChannelCount,
new ThreadSharedFloatArrayBufferList(aChannelCount);
for (uint32_t i = 0; i < aChannelCount; ++i) {
float* channelData = js_pod_malloc<float>(aLength);
float* channelData = js_pod_calloc<float>(aLength);
if (!channelData) {
return nullptr;
}
+2 -2
View File
@@ -40,8 +40,8 @@ public:
}
/**
* Create with buffers suitable for transfer to
* JS_NewArrayBufferWithContents(). The buffer contents are uninitialized
* and so should be set using GetDataForWrite().
* JS_NewArrayBufferWithContents(). The buffer contents are
* zero-initialized; callers should set them using GetDataForWrite().
*/
static already_AddRefed<ThreadSharedFloatArrayBufferList>
Create(uint32_t aChannelCount, size_t aLength, const mozilla::fallible_t&);
+160
View File
@@ -577,6 +577,166 @@ typedef struct _NPEvent
} NPEvent;
#elif defined(XP_UNIX) && defined(MOZ_X11)
typedef XEvent NPEvent;
#elif defined(XP_UNIX) && defined(MOZ_WIDGET_HEADLESS)
/*
* JIHAD (webOS, cavekit-addons-extensions.md R7) — THE PALM EVENT PROTOCOL.
*
* webOS plugins do not speak X11. Palm's own npapi.h defines NPEvent, under XP_WEBOS, as the
* union below; the device's Adobe Flash was compiled against exactly that header and its
* NPP_HandleEvent reads these fields. Reproduced here from the webOS WebKit fork's
* WebCore/plugins/npapi.h (the XP_WEBOS block, NpPalmEventsEnum through the NPEvent union),
* so that the shape crossing our NPAPI boundary is the shape the plugin was built to read.
*
* This replaces `typedef void* NPEvent` for the headless toolkit, and that arm was not merely
* a placeholder — it was load-bearing in the wrong direction. NPRemoteEvent is a raw memcpy of
* sizeof(NPEvent) (dom/plugins/ipc/NPEventUnix.h), so with a void* NPEvent the parent shipped
* four bytes of its own address space to the child and the child handed the plugin a pointer
* into a foreign process. No event could ever have carried a payload. Making NPEvent a real
* POD is what lets the whole existing NPP_HandleEvent path work unmodified, parent to child.
*
* Gated on MOZ_WIDGET_HEADLESS because that is precisely the configuration this port builds
* (--enable-default-toolkit=cairo-headless, no X anywhere in the bundle) and the only one that
* reaches this arm. A non-webOS headless embedding would get these structs too; that is
* harmless, since the alternative it loses is an NPEvent that could not carry an event.
*
* POINTER-BEARING MEMBERS DO NOT SURVIVE IPC. dstBuffer/graphicsContext (draw),
* touches (touch) and reserved (system) are process-local. Pen, key and system events use
* none of them; the draw event is built inside the child (PluginInstanceChild.cpp) and never
* crosses the boundary, which is why it stays valid.
*
* One deliberate omission from Palm's union: NpPalmAccelerometerEvent. It is 16 bytes against
* NpPalmDrawEvent's 44, so leaving it out changes sizeof(NPEvent) by nothing — and the union
* is only ever read through the plugin's OWN copy of this declaration, so an unused member
* here is unobservable. It is left out rather than copied because it carries a struct-scoped
* `enum Orientation` whose tag would leak to file scope, for no gain.
*/
typedef enum NpPalmEventsEnum
{
npPalmPenDownEvent = 1 << 0,
npPalmPenUpEvent = 1 << 1,
npPalmPenMoveEvent = 1 << 2,
npPalmKeyDownEvent = 1 << 3,
npPalmKeyUpEvent = 1 << 4,
npPalmKeyRepeatEvent = 1 << 5,
npPalmKeyPressEvent = 1 << 6,
npPalmDrawEvent = 1 << 7,
npPalmSystemEvent = 1 << 8,
npPalmGestureEvent = 1 << 9,
npPalmAccelerometerEvent = 1 << 10,
npPalmTouchStartEvent = 1 << 11,
npPalmTouchMoveEvent = 1 << 12,
npPalmTouchEndEvent = 1 << 13,
npPalmTouchCancelledEvent = 1 << 14,
npPalmPenDoubleClickEvent = 1 << 15,
npPalmPenClickEvent = 1 << 16
} NpPalmEventsEnum;
typedef enum NpPalmSystemEventsEnum
{
npPalmPauseEvent = 1,
npPalmResumeEvent = 2,
npPalmGainFocusEvent = 3,
npPalmLoseFocusEvent = 4,
npPalmDimmedEvent = 5,
npPalmSetFullScreenEvent = 6,
npPalmUnsetFullScreenEvent = 7,
npPalmPageLoadingEvent = 8,
npPalmPageLoadCompleteEvent = 9,
npPalmViewPortChangedEvent = 10,
npPalmSpotlightStartEvent = 11,
npPalmSpotlightEndEvent = 12
} NpPalmSystemEventsEnum;
typedef enum NpPalmKeyModifiersEnum
{
npPalmCtrlKeyModifier = 1 << 0,
npPalmAltKeyModifier = 1 << 1,
npPalmShiftKeyModifier = 1 << 2,
npPalmMetaKeyModifier = 1 << 3
} NpPalmKeyModifiersEnum;
typedef struct NpPalmKeyEvent
{
int32_t chr; /* 32-bit so any Unicode character fits */
int32_t modifiers;
int32_t rawkeyCode;
int32_t rawModifier;
} NpPalmKeyEvent;
typedef struct NpPalmPenEvent
{
int32_t xCoord, yCoord; /* plugin-local, in the plugin's own unscaled pixels */
int32_t modifiers;
} NpPalmPenEvent;
typedef struct NpPalmTouchPoint
{
int32_t xCoord, yCoord;
} NpPalmTouchPoint;
typedef struct NpPalmTouchEvent
{
int32_t touchCount;
NpPalmTouchPoint* touches; /* process-local — never send over IPC */
int32_t modifiers;
} NpPalmTouchEvent;
typedef struct NpPalmDrawEvent
{
void* dstBuffer; /* process-local; API 1.0 raster destination */
uint32_t dstRowBytes;
int32_t srcLeft;
int32_t srcRight;
int32_t srcTop;
int32_t srcBottom;
void* graphicsContext; /* process-local; the Piranha PGContext, API 2.0 */
int32_t dstLeft;
int32_t dstRight;
int32_t dstTop;
int32_t dstBottom;
} NpPalmDrawEvent;
typedef struct NpPalmSystemEvent
{
NpPalmSystemEventsEnum type;
int32_t value;
int32_t viewLeft;
int32_t viewRight;
int32_t viewTop;
int32_t viewBottom;
void* reserved; /* process-local */
} NpPalmSystemEvent;
typedef enum NpPalmGestureEventEnum
{
npPalmGestureStartEvent = 1,
npPalmGestureChangeEvent = 2,
npPalmGestureEndEvent = 3,
npPalmGestureSingleTapEvent = 4
} NpPalmGestureEventEnum;
typedef struct NpPalmGestureEvent
{
NpPalmGestureEventEnum type;
int32_t x, y;
float scale, rotate;
int32_t center_x, center_y;
int32_t modifiers;
} NpPalmGestureEvent;
typedef struct NPEvent
{
NpPalmEventsEnum eventType;
union {
NpPalmKeyEvent keyEvent;
NpPalmPenEvent penEvent;
NpPalmDrawEvent drawEvent;
NpPalmSystemEvent systemEvent;
NpPalmGestureEvent gestureEvent;
NpPalmTouchEvent touchEvent;
} data;
} NPEvent;
#else
typedef void* NPEvent;
#endif
+15 -1
View File
@@ -341,6 +341,10 @@ nsNPAPIPlugin::CreatePlugin(nsPluginTag *aPluginTag, nsNPAPIPlugin** aResult)
RefPtr<nsNPAPIPlugin> plugin = new nsNPAPIPlugin();
PluginLibrary* pluginLib = GetNewPluginLibrary(aPluginTag);
// JIHAD DIAGNOSTIC (R7): GetNewPluginLibrary is where the OOP decision is made —
// RunPluginOOP() ? PluginModuleParent::LoadModule (launches plugin-container) : a
// PluginPRLibrary loaded in-process. A null here is the plugin-container launch failing.
fprintf(stderr, "[jihad-npapi] GetNewPluginLibrary lib=%d\n", (int)!!pluginLib);
if (!pluginLib) {
return NS_ERROR_FAILURE;
}
@@ -386,6 +390,7 @@ nsNPAPIPlugin::CreatePlugin(nsPluginTag *aPluginTag, nsNPAPIPlugin** aResult)
#else
NPError pluginCallError;
nsresult rv = pluginLib->NP_Initialize(&sBrowserFuncs, &plugin->mPluginFuncs, &pluginCallError);
fprintf(stderr, "[jihad-npapi] NP_Initialize rv=0x%x npErr=%d\n", (unsigned)rv, (int)pluginCallError);
if (rv != NS_OK || pluginCallError != NPERR_NO_ERROR) {
return NS_ERROR_FAILURE;
}
@@ -1939,7 +1944,16 @@ _getvalue(NPP npp, NPNVariable variable, void *result)
}
case NPNVSupportsWindowless: {
#if defined(XP_WIN) || defined(XP_MACOSX) || \
// MOZ_WIDGET_HEADLESS added for Jihad Browser. This list enumerates the toolkits that can
// host a windowless plugin, and it was written before a headless toolkit existed — so a
// cairo-headless build answered "windowless unsupported" to every plugin, which is the
// opposite of the truth. Headless is the toolkit that MOST needs windowless: there is no X
// server, no Drawable and no XEmbed, so windowed hosting is impossible and drawing into a
// memory bitmap we own is the only thing that can work. gfxPlatformHeadless already returns
// true from SupportsPluginDirectBitmapDrawing(), i.e. the drawing model this unlocks
// (NPDrawingModelAsyncBitmapSurface) is implemented for this platform; only this
// advertisement was missing, and with it false no plugin would ever choose windowless.
#if defined(XP_WIN) || defined(XP_MACOSX) || defined(MOZ_WIDGET_HEADLESS) || \
(defined(MOZ_X11) && defined(MOZ_WIDGET_GTK))
*(NPBool*)result = true;
#else
+69 -1
View File
@@ -843,6 +843,9 @@ nsPluginHost::InstantiatePluginInstance(const nsACString& aMimeType, nsIURI* aUR
}
rv = SetUpPluginInstance(aMimeType, aURL, instanceOwner);
// JIHAD DIAGNOSTIC (R7): the real rv is flattened to NS_ERROR_FAILURE below, which is what
// made this failure opaque from the caller's side.
fprintf(stderr, "[jihad-npapi] SetUpPluginInstance rv=0x%x\n", (unsigned)rv);
if (NS_FAILED(rv)) {
instanceOwner->Destroy();
return NS_ERROR_FAILURE;
@@ -961,7 +964,12 @@ nsPluginHost::TrySetUpPluginInstance(const nsACString &aMimeType,
#endif
RefPtr<nsNPAPIPlugin> plugin;
GetPlugin(aMimeType, getter_AddRefs(plugin));
nsresult jihadGetRv = GetPlugin(aMimeType, getter_AddRefs(plugin));
// JIHAD DIAGNOSTIC (R7): GetPlugin -> CreateNPAPIPlugin -> nsNPAPIPlugin::CreatePlugin, which
// for an OOP build is PluginModuleParent::LoadModule (the plugin-container launch). Its rv is
// DISCARDED here; only the null check survives, so a launch failure is invisible.
fprintf(stderr, "[jihad-npapi] GetPlugin rv=0x%x plugin=%d\n",
(unsigned)jihadGetRv, (int)!!plugin);
if (!plugin) {
return NS_ERROR_FAILURE;
}
@@ -987,6 +995,7 @@ nsPluginHost::TrySetUpPluginInstance(const nsACString &aMimeType,
// except in some cases not Java, see bug 140931
// our COM pointer will free the peer
nsresult rv = instance->Initialize(plugin.get(), aOwner, aMimeType);
fprintf(stderr, "[jihad-npapi] instance->Initialize rv=0x%x\n", (unsigned)rv);
if (NS_FAILED(rv)) {
mInstances.RemoveElement(instance.get());
aOwner->SetInstance(nullptr);
@@ -4201,3 +4210,62 @@ PluginDestructionGuard::DelayDestroy(nsNPAPIPluginInstance *aInstance)
return false;
}
// ── JIHAD (webOS, cavekit-addons-extensions.md R7) ────────────────────────────────────────
//
// A C entry point for the render daemon, following the jihad_offscreen_* precedent in
// widget/PuppetWidget.cpp: the daemon links against libxul but cannot see internal classes,
// and nsNPAPIPluginInstance::HandleEvent is neither exported nor virtual, so there is no
// other way to reach a plugin from outside.
//
// This exists for the frozen YAP command pair asyncCmdPluginSpotlightStart/End. The card
// scrims and smart-zooms to a plugin, then tells the server the rect it settled on; the
// server's job is to pass that on to the plugin as Palm's npPalmSpotlightStartEvent(11) /
// npPalmSpotlightEndEvent(12). It is not cosmetic: Flash routes 11 to the same handler as
// npPalmSetFullScreenEvent(6) and 12 to the same as npPalmUnsetFullScreenEvent(7)
// (libflashplayer.so jump table at 0x44e0c — entries 10 and 11 target 0x44fa0/0x44e80,
// identical to entries 5 and 6), so this is how a plugin is told it went fullscreen.
//
// Broadcast to every running instance rather than targeting one: the spotlight is a
// page-level, one-plugin-at-a-time state, this daemon serves a single card, and the
// alternative — matching the rect against each instance's frame — would invent a
// disambiguation rule that the contract does not define. Returns how many instances were
// told, so a caller can tell "no plugin" from "delivered".
extern "C" MOZ_EXPORT int
jihad_plugin_palm_spotlight(int aOn, int aLeft, int aTop, int aRight, int aBottom)
{
#ifdef MOZ_ENABLE_NPAPI
RefPtr<nsPluginHost> host = nsPluginHost::GetInst();
if (!host) {
return 0;
}
NPEvent ev;
memset(&ev, 0, sizeof(ev));
ev.eventType = npPalmSystemEvent;
ev.data.systemEvent.type = aOn ? npPalmSpotlightStartEvent : npPalmSpotlightEndEvent;
// Palm's host leaves systemEvent.value uninitialised here and fills only the rect
// (libWebKitLuna handlePluginSpotlightStart 0x4e6cec-0x4e6d24, which never writes [sp+8]).
// The memset above zeroes it, which is strictly tidier and observably the same.
ev.data.systemEvent.viewLeft = aLeft;
ev.data.systemEvent.viewTop = aTop;
ev.data.systemEvent.viewRight = aRight;
ev.data.systemEvent.viewBottom = aBottom;
int delivered = 0;
// Copy the instance list first: HandleEvent re-enters the plugin, which may run script and
// tear an instance down underneath us.
nsTArray<RefPtr<nsNPAPIPluginInstance>> instances(host->JihadRunningInstances());
for (uint32_t i = 0; i < instances.Length(); ++i) {
int16_t response = kNPEventNotHandled;
if (NS_SUCCEEDED(instances[i]->HandleEvent(&ev, &response,
NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO))) {
delivered++;
}
}
return delivered;
#else
(void)aOn; (void)aLeft; (void)aTop; (void)aRight; (void)aBottom;
return 0;
#endif
}
+7
View File
@@ -274,6 +274,13 @@ public:
InfallibleTArray<nsCString>& result,
bool firstMatchOnly);
// Jihad R7 (webOS): a snapshot of the live instances, for jihad_plugin_palm_spotlight.
// A COPY, not a reference: dispatching an event re-enters the plugin, which can run script
// and destroy an instance, and mInstances is mutated by that teardown.
const nsTArray<RefPtr<nsNPAPIPluginInstance>>& JihadRunningInstances() const {
return mInstances;
}
private:
friend class nsPluginUnloadRunnable;
+216 -14
View File
@@ -569,6 +569,75 @@ NS_IMETHODIMP nsPluginInstanceOwner::InvalidateRect(NPRect *invalidRect)
GetContentsScaleFactor(&scaleFactor);
rect.ScaleRoundOut(scaleFactor);
mPluginFrame->InvalidateLayer(nsDisplayItem::TYPE_PLUGIN, &rect);
// JIHAD (2026-08-09): drive the offscreen daemon's re-capture for WINDOWLESS plugins.
//
// A windowless plugin has no mWidget, so the mWidget->Invalidate() branch above (which is what
// ultimately reaches PuppetWidget::Invalidate and sets the daemon's mJihadDirty flag) never
// runs. InvalidateLayer() alone only marks the plugin's ImageLayer for recomposition; with the
// in-process BasicLayerManager and no separate compositor, that repaints the widget's own layer
// backbuffer but never triggers jihad_offscreen_render_region, the path that actually renders a
// frame into the adapter's shared buffer for the card. Measured: Flash pushes a fresh magenta
// frame into its ImageContainer ~15x/s and BasicImageLayer::Paint runs on each, yet
// render_region fired ONCE (at load) so the card froze on the pre-content frame. The control
// plugin only appeared to work because its static fill was already present at that single
// capture. Invalidate the nearest real widget here so every async plugin frame marks the daemon
// dirty and gets composited to the card.
//
// THE RECT MATTERS, and the first version of this got it wrong. It invalidated
// nearest->GetBounds() — the WIDGET's bounds, i.e. the whole viewport — on the reasoning
// that the daemon re-renders the whole document per capture anyway. That reasoning stopped
// being true when the daemon learned to repaint only the damaged rows: a whole-viewport
// software render costs ~40 ms on this hardware against ~4 ms for a 320x240 plugin box, and
// a full-viewport damage box silently forced the expensive path on every single frame.
// Measured: an animated SWF ran at 19 fps with 1 partial repaint in 39, and the damage box
// logged as 768x942 with the plugin's own 320x240 unioned uselessly into it.
//
// So invalidate the plugin's own area, translated from plugin-local into the widget's
// coordinates the same way the rest of this file does it: content-box origin relative to the
// frame, offset to the widget, in device px.
if (!mWidget) {
nsIWidget* nearest = mPluginFrame->GetNearestWidget();
if (nearest) {
nsIntRect widgetRect = rect;
nsPresContext* pc = mPluginFrame->PresContext();
// Offset to the ROOT frame, which is what the widget's coordinates are relative to.
// GetReferenceFrame() was the first attempt and it is wrong here: for a plugin it
// resolves to a frame that makes the offset come out 0, so every invalidation landed at
// the viewport's top-left corner instead of on the plugin. That is not a small error —
// the damage-only repaint then faithfully refreshed the wrong 320x240 box and the
// plugin's own area never updated again, which reads on screen as the animation
// freezing after its first frame. This is the same offset nsPluginFrame itself uses to
// build NPWindow.x/y.
nsIFrame* rootFrame = nullptr;
if (nsIPresShell* ps = mPluginFrame->PresContext()->GetPresShell()) {
rootFrame = ps->GetRootFrame();
}
nsPoint origin = mPluginFrame->GetContentRectRelativeToSelf().TopLeft() +
(rootFrame ? mPluginFrame->GetOffsetToCrossDoc(rootFrame) : nsPoint());
widgetRect.MoveBy(pc->AppUnitsToDevPixels(origin.x),
pc->AppUnitsToDevPixels(origin.y));
// A plugin is entitled to report an invalid rect larger than itself, and an empty one
// would invalidate nothing at all; clamp to the plugin's own box, and fall back to the
// widget bounds if that leaves nothing (correctness before speed).
nsIntRect pluginBox(pc->AppUnitsToDevPixels(origin.x),
pc->AppUnitsToDevPixels(origin.y),
pc->AppUnitsToDevPixels(
mPluginFrame->GetContentRectRelativeToSelf().width),
pc->AppUnitsToDevPixels(
mPluginFrame->GetContentRectRelativeToSelf().height));
widgetRect = widgetRect.Intersect(pluginBox);
if (widgetRect.IsEmpty()) {
widgetRect = pluginBox;
}
if (widgetRect.IsEmpty()) {
nearest->Invalidate(nearest->GetBounds());
} else {
nearest->Invalidate(LayoutDeviceIntRect(widgetRect.x, widgetRect.y,
widgetRect.width, widgetRect.height));
}
}
}
return NS_OK;
}
@@ -2530,6 +2599,122 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const WidgetGUIEvent& anEvent)
rv = nsEventStatus_eConsumeNoDefault;
#endif
// Guard MUST match the one npapi.h uses to define NPEvent as Palm's union. Any other
// predicate compiles this against `typedef void* NPEvent` and does not build.
#if defined(XP_UNIX) && defined(MOZ_WIDGET_HEADLESS)
// JIHAD (webOS, cavekit-addons-extensions.md R7) — DELIVER INPUT IN THE PALM PROTOCOL.
//
// Everything above this point is a platform arm: XP_MACOSX, XP_WIN, MOZ_X11. A
// cairo-headless build matches none of them, so this function used to reduce to
// `return nsEventStatus_eIgnore;` and a windowless plugin received no mouse, key, focus or
// blur event in its whole lifetime. Measured on the TouchPad before this branch existed: a
// tap hit-tested the <EMBED>, the daemon logged `mouseSend <EMBED> ... : down`, and the
// plugin's NPP_HandleEvent was called exactly once ever — for the child's own gain-focus
// injection. Nothing upstream is at fault; the DOM listeners, the hit test, the windowless
// guards and the IPC hop are all live and correct (see the Dispatch*ToPlugin callers).
//
// The event shape is Palm's, because NPEvent on this platform IS Palm's union (npapi.h) and
// the device's Flash was compiled against that declaration.
{
NPEvent pluginEvent;
memset(&pluginEvent, 0, sizeof(pluginEvent));
if (anEvent.mClass == eMouseEventClass) {
const WidgetMouseEvent& mouseEvent = *anEvent.AsMouseEvent();
switch (anEvent.mMessage) {
case eMouseDown: pluginEvent.eventType = npPalmPenDownEvent; break;
case eMouseUp: pluginEvent.eventType = npPalmPenUpEvent; break;
case eMouseMove: pluginEvent.eventType = npPalmPenMoveEvent; break;
// The synthesized click/dblclick that follows a down/up pair. Palm's host sends these
// as their own event types rather than swallowing them (libWebKitLuna
// handleMouseEvent 0x4e946c-0x4e94d8 maps click -> 65536 and dblclick -> 32768, in
// ADDITION to the down/up pair, not instead of it), so this is what a plugin written
// for webOS was built to see. The X11 arm above drops them instead, which is right
// for X11 and wrong here.
//
// Flash itself ignores both: its NPP_HandleEvent jump table (libflashplayer.so
// 0x4514c-0x4522c) compares only against 1/2/4/8/16/64/128/256/512, and anything
// else falls through to "not handled" — confirmed on device, where a tap logs
// `palm event 0x10000 ... handled=0` between two handled pen events. Sending them
// anyway is deliberate: the contract is the host's, not this one plugin's, and a
// plugin that acts only on the click is otherwise silently unusable.
case eMouseClick: pluginEvent.eventType = npPalmPenClickEvent; break;
case eMouseDoubleClick: pluginEvent.eventType = npPalmPenDoubleClickEvent; break;
default: break; // over/out/wheel/aux: no Palm equivalent, drop
}
if (pluginEvent.eventType) {
// The plugin-local point, computed exactly as the MOZ_X11 arm above computes it. This
// is also what Palm's own host does — PluginView's webOS block uses the renderer's
// absoluteToLocal() on the same absolute location — so the two hosts agree on the
// space without either being ported to the other.
//
// Deliberately NO zoom or scroll arithmetic here. The card's fit-zoom is not an engine
// zoom (it is applied when the daemon scales the capture context), layout.css.
// devPixelsPerPx is pinned to 1.0, and the daemon has already mapped card px to CSS
// viewport px before dispatching. Adding a factor here is how plugin input drifts away
// from where page content thinks it was clicked; the criterion is that both go through
// the same transform, and they do precisely because this arm adds none.
const nsPresContext* presContext = mPluginFrame->PresContext();
nsPoint appPoint =
nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mPluginFrame) -
mPluginFrame->GetContentRectRelativeToSelf().TopLeft();
pluginEvent.data.penEvent.xCoord =
presContext->AppUnitsToDevPixels(appPoint.x);
pluginEvent.data.penEvent.yCoord =
presContext->AppUnitsToDevPixels(appPoint.y);
pluginEvent.data.penEvent.modifiers =
(mouseEvent.IsControl() ? npPalmCtrlKeyModifier : 0) |
(mouseEvent.IsAlt() ? npPalmAltKeyModifier : 0) |
(mouseEvent.IsShift() ? npPalmShiftKeyModifier : 0) |
(mouseEvent.IsMeta() ? npPalmMetaKeyModifier : 0);
}
} else if (anEvent.mClass == eKeyboardEventClass) {
const WidgetKeyboardEvent& keyEvent = *anEvent.AsKeyboardEvent();
switch (anEvent.mMessage) {
case eKeyDown: pluginEvent.eventType = npPalmKeyDownEvent; break;
case eKeyUp: pluginEvent.eventType = npPalmKeyUpEvent; break;
case eKeyPress: pluginEvent.eventType = npPalmKeyPressEvent; break;
default: break;
}
if (pluginEvent.eventType) {
// There is no native key event to copy from on this platform (mPluginEvent is a
// Windows concept), so the Palm fields are synthesized from the widget event.
// rawkeyCode/rawModifier are Palm's "pass the unprocessed event through" pair, which
// for a synthesized event is the same key code and modifier set.
int32_t mods =
(keyEvent.IsControl() ? npPalmCtrlKeyModifier : 0) |
(keyEvent.IsAlt() ? npPalmAltKeyModifier : 0) |
(keyEvent.IsShift() ? npPalmShiftKeyModifier : 0) |
(keyEvent.IsMeta() ? npPalmMetaKeyModifier : 0);
pluginEvent.data.keyEvent.chr =
static_cast<int32_t>(keyEvent.PseudoCharCode());
pluginEvent.data.keyEvent.modifiers = mods;
pluginEvent.data.keyEvent.rawkeyCode = static_cast<int32_t>(keyEvent.mKeyCode);
pluginEvent.data.keyEvent.rawModifier = mods;
}
} else if (anEvent.mMessage == eFocus || anEvent.mMessage == eBlur) {
// Focus arrives as a bare WidgetGUIEvent with a null widget (see DispatchFocusToPlugin),
// so it must not touch the coordinate path above.
pluginEvent.eventType = npPalmSystemEvent;
pluginEvent.data.systemEvent.type =
(anEvent.mMessage == eFocus) ? npPalmGainFocusEvent : npPalmLoseFocusEvent;
}
if (pluginEvent.eventType) {
int16_t response = kNPEventNotHandled;
mInstance->HandleEvent(&pluginEvent, &response,
NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO);
if (response == kNPEventHandled) {
rv = nsEventStatus_eConsumeNoDefault;
}
}
}
#endif
return rv;
}
@@ -2977,23 +3162,40 @@ NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void)
if (!mWidget) {
// native (single process)
mWidget = do_CreateInstance(kWidgetCID, &rv);
nsWidgetInitData initData;
initData.mWindowType = eWindowType_plugin;
initData.mUnicode = false;
initData.clipChildren = true;
initData.clipSiblings = true;
rv = mWidget->Create(parentWidget.get(), nullptr,
LayoutDeviceIntRect(0, 0, 0, 0), &initData);
if (NS_FAILED(rv)) {
mWidget->Destroy();
mWidget = nullptr;
return rv;
if (!mWidget) {
// JIHAD (2026-10-05): A BUILD WITH NO CHILD-WINDOW WIDGET HAS NO WINDOWED PLUGINS.
// The offscreen embedding registers no widget for kWidgetCID, so this came back
// null and the Create() call below dereferenced it: the daemon died with SIGSEGV on
// every page whose Flash movie was embedded the ordinary way. A plugin is windowed
// unless it asks otherwise, and Flash asks only for wmode=opaque/transparent — the
// default, wmode=window, is what most of the web uses (found on two "Flash test"
// sites; every test page of ours had wmode=opaque). webOS's own browser never had
// plugin windows either and handed every plugin a drawable; its Flash build draws
// through the Palm window structure in both modes. So do the same: with no window
// to give, the instance is windowless.
mInstance->SetWindowless(true);
windowless = true;
} else {
nsWidgetInitData initData;
initData.mWindowType = eWindowType_plugin;
initData.mUnicode = false;
initData.clipChildren = true;
initData.clipSiblings = true;
rv = mWidget->Create(parentWidget.get(), nullptr,
LayoutDeviceIntRect(0, 0, 0, 0), &initData);
if (NS_FAILED(rv)) {
mWidget->Destroy();
mWidget = nullptr;
return rv;
}
}
}
mWidget->EnableDragDrop(true);
mWidget->Show(false);
mWidget->Enable(false);
if (mWidget) {
mWidget->EnableDragDrop(true);
mWidget->Show(false);
mWidget->Enable(false);
}
}
if (mPluginFrame) {
+11 -1
View File
@@ -133,6 +133,12 @@ BrowserStreamChild::RecvNPP_DestroyStream(const NPReason& reason)
{
PLUGIN_LOG_DEBUG_METHOD;
// Jihad R7: end-of-stream is what tells a Flash player the movie is complete. A player that
// is never told stops on frame zero, which looks exactly like a player that cannot draw.
fprintf(stderr, "[jihad-npapi-child] RecvNPP_DestroyStream reason=%d state=%d\n",
(int)reason, (int)mState);
fflush(stderr);
if (ALIVE != mState)
NS_RUNTIMEABORT("Unexpected state: recevied NPP_DestroyStream twice?");
@@ -232,8 +238,12 @@ BrowserStreamChild::Deliver()
if (kStreamOpen == mStreamStatus)
mStreamStatus = NPRES_DONE;
(void) mInstance->mPluginIface
NPError dsrv = mInstance->mPluginIface
->destroystream(&mInstance->mData, &mStream, mStreamStatus);
// Jihad R7: the delivery site, as opposed to RecvNPP_DestroyStream which only queues it.
fprintf(stderr, "[jihad-npapi-child] NPP_DestroyStream status=%d rv=%d\n",
(int)mStreamStatus, (int)dsrv);
fflush(stderr);
}
if (DESTROYED == mDestroyPending && mNotifyPending) {
NS_ASSERTION(mStreamNotify, "mDestroyPending but no mStreamNotify?");
+74
View File
@@ -0,0 +1,74 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* NPN entry points exported as GLOBAL SYMBOLS, for plugins that expect the old Netscape
* convention where the host browser exports them rather than only passing an NPNetscapeFuncs
* table to NP_Initialize.
*
* WHY THIS IS ITS OWN TRANSLATION UNIT. The obvious place for these is PluginModuleChild.cpp,
* and it does not work: npapi.h already declares NPN_InvalidateRect, and every header in this
* build is compiled under `-include config/gcc_hidden.h`, which pushes hidden visibility. GCC
* takes visibility from the FIRST declaration it sees, so a later definition carrying
* __attribute__((visibility("default"))) is silently ignored and the symbol lands in the
* object as GLOBAL HIDDEN — present to `nm`, absent from the dynamic table, and therefore
* impossible to interpose. Verified with readelf. This file deliberately includes no NPAPI
* headers at all and describes the functions with void* so there is no prior declaration to
* inherit hidden visibility from.
*
* WHY IT MATTERS. webOS's Flash imports NPN_CreateObject and NPN_InvalidateRect as undefined
* dynamic symbols. Left alone they bind into libWebKitLuna.so — another browser engine that
* is in this process because Flash (and our Piranha drawing path) pull it in. Two consequences,
* both measured:
* 1. Flash's repaint requests go to LunaSysMgr's WebKit and never reach our engine, so the
* plugin is only ever painted when something else happens to invalidate it. That alone
* makes an animating plugin look frozen.
* 2. It is a latent crash: UXP stores a PluginInstanceChild* in NPP::ndata, while
* libWebKitLuna's NPN_InvalidateRect casts that same field to a WebCore::PluginView* and
* makes a virtual call on it — a wild vtable dispatch on the first repaint.
*
* The forwarding pointers are installed by PluginModuleChild once the browser function table
* exists; until then these are safe no-ops.
*/
#include <stdio.h>
extern "C" {
void (*gJihadNPNInvalidateRect)(void* aNPP, void* aRect) = 0;
void* (*gJihadNPNCreateObject)(void* aNPP, void* aClass) = 0;
// Read by the host repaint clock in PluginInstanceChild.cpp: while this is zero the plugin has
// never asked to be repainted, so the host has to drive it.
unsigned gJihadNPNInvalidateRectCalls = 0;
__attribute__((visibility("default"))) void
NPN_InvalidateRect(void* aNPP, void* aRect)
{
// The first call is the signal that the plugin's frame clock is finally running; without
// it the plugin is only ever painted by an unrelated invalidation, which is
// indistinguishable on screen from a plugin that draws nothing. Log it once, and log the
// no-forwarder case too — arriving before PluginModuleChild installs the pointers is a
// dropped repaint, not a no-op.
gJihadNPNInvalidateRectCalls++;
static int sLogged = 0;
if (sLogged < 8) {
sLogged++;
fprintf(stderr, "[jihad-npapi-child] NPN_InvalidateRect npp=%p rect=%p fwd=%p\n",
aNPP, aRect, (void*)gJihadNPNInvalidateRect);
fflush(stderr);
}
if (gJihadNPNInvalidateRect) {
gJihadNPNInvalidateRect(aNPP, aRect);
}
}
__attribute__((visibility("default"))) void*
NPN_CreateObject(void* aNPP, void* aClass)
{
return gJihadNPNCreateObject ? gJihadNPNCreateObject(aNPP, aClass) : 0;
}
} // extern "C"
+23
View File
@@ -125,6 +125,29 @@ child:
// of its parent has changed
async ContentsScaleFactorChanged(double aContentsScaleFactor);
// Jihad (webOS, cavekit-addons-extensions.md R7): ask the plugin for ONE frame, now.
//
// Palm's host issued npPalmDrawEvent every time the PAGE painted, so Flash can sit on its own
// frame clock and expect to be asked. Patch 0026 got it drawing by giving the CHILD a timer,
// but that timer free-runs against the daemon's tick, so a frame lands at a drifting phase and
// waits up to a whole tick to be published. Measured on device with a 30 fps SWF: 1:1 delivery
// and a 31-34 ms average, but a gap spread of 9-62 ms, which is what the eye reads as stutter.
//
// CAUTION, measured 2026-08-10 and it contradicts what 0026 assumed: the plugin DOES invalidate
// itself, ~22 times a second, alongside our ~27. The counter 0026 reads to conclude otherwise
// (gJihadNPNInvalidateRectCalls) only sees calls that bind the NPN_InvalidateRect SYMBOL, and
// an ordinary NPAPI plugin goes through the NPNetscapeFuncs table instead. So this message is
// currently a SECOND producer rather than the only one, and whether it should exist at all for
// a self-invalidating plugin is open — see the R7 frame-rate criterion.
//
// This is the pull that removes the second clock. ASYNC on purpose: the stock host pulls the
// plugin synchronously inside its page paint (PluginViewPalm), but out-of-process that shape
// is intr NPP_HandleEvent, which would block the daemon's main thread — and therefore its
// tick and its YAP socket — for a full IPC round trip plus a Flash paint on every frame.
// Async keeps the phase lock and costs nothing: the child coalesces duplicate requests via
// mCurrentInvalidateTask, so an extra request while one is in flight is a no-op.
async JihadRequestFrame();
// ********************** Async plugins rendering
// see https://wiki.mozilla.org/Gecko:AsyncPluginPainting
// **********************
File diff suppressed because it is too large. Load diff
+23 -1
View File
@@ -36,7 +36,7 @@
#include <map>
#ifdef MOZ_WIDGET_GTK
#ifdef MOZ_ENABLE_NPAPI_GTK2
#include "gtk2xtbin.h"
#endif
@@ -141,6 +141,10 @@ protected:
virtual bool
RecvContentsScaleFactorChanged(const double& aContentsScaleFactor) override;
// Jihad: the host is driving the frame clock — draw one now. See PPluginInstance.ipdl.
virtual bool
RecvJihadRequestFrame() override;
virtual bool
AnswerNPP_Destroy(NPError* result) override;
@@ -462,6 +466,8 @@ private:
NPSetWindowCallbackStruct mWsInfo;
#ifdef MOZ_WIDGET_GTK
bool mXEmbed;
#endif
#ifdef MOZ_ENABLE_NPAPI_GTK2
XtClient mXtClient;
#endif
#elif defined(OS_WIN)
@@ -639,6 +645,22 @@ private:
// and p->getvalue return always false
bool mIsTransparent;
// Jihad R7 (webOS): npPalmGainFocusEvent is a once-per-instance startup signal, but the
// setwindow that carries it runs again on every resize and scroll.
bool mJihadSentPalmGainFocus;
// Jihad R7 (webOS): cap on the input-delivery breadcrumb in AnswerNPP_HandleEvent. A
// pen-move stream is unbounded; the daemon log is the only field-debug channel there is.
uint32_t mJihadInputEventsLogged;
public:
// Jihad R7 (webOS): repaint this instance from the host's own clock. See
// JihadGlibPumpTask::Run — a webOS plugin is not obliged to ask for repaints, because the
// host it was written for painted it as part of every page paint.
void JihadPalmRepaintTick();
private:
// Surface type optimized of parent process
gfxSurfaceType mSurfaceType;
+224 -7
View File
@@ -115,6 +115,16 @@ PluginInstanceParent::LookupPluginInstanceByID(uintptr_t aId)
}
#endif
// Jihad: every live instance, so a C entry point can reach one. jihad_plugin_frame_seq needs no
// instance because it only counts; a frame REQUEST has to be sent on an actual actor.
//
// A plain file-static array maintained in the ctor/dtor below, not a hashtable: this is at most a
// couple of entries on a single-card embedding, it is only ever touched on the main thread (the
// daemon calls the export from inside its own tick, on that same thread), and the alternative —
// walking nsPluginHost's nsNPAPIPluginInstance list the way jihad_plugin_palm_spotlight does —
// would still have to get from there to the PluginInstanceParent actor to call Send on it.
static nsTArray<PluginInstanceParent*>* gJihadLiveInstances = nullptr;
PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
NPP npp,
const nsCString& aMimeType,
@@ -145,10 +155,24 @@ PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
sPluginInstanceList = new nsClassHashtable<nsVoidPtrHashKey, PluginInstanceParent>();
}
#endif
// Jihad: join the live list that jihad_plugin_request_frame walks. Leaked on purpose — it
// outlives every instance and there is no shutdown hook here that is guaranteed to run
// after the last dtor.
if (!gJihadLiveInstances) {
gJihadLiveInstances = new nsTArray<PluginInstanceParent*>();
}
gJihadLiveInstances->AppendElement(this);
}
PluginInstanceParent::~PluginInstanceParent()
{
// Jihad: leave the live list FIRST. Anything below can run script or spin the loop, and a
// frame request delivered to a half-destroyed actor is a use-after-free rather than a
// dropped frame.
if (gJihadLiveInstances) {
gJihadLiveInstances->RemoveElement(this);
}
if (mNPP)
mNPP->pdata = nullptr;
@@ -269,6 +293,8 @@ PluginInstanceParent::AnswerNPN_GetValue_NPNVnetscapeWindow(NativeWindowHandle*
XID id;
#elif defined(XP_DARWIN)
intptr_t id;
#elif defined(MOZ_WIDGET_HEADLESS)
intptr_t id; // Jihad headless: no native window id
#else
#warning Implement me
#endif
@@ -769,6 +795,51 @@ PluginInstanceParent::RecvShowDirectBitmap(Shmem&& buffer,
return false;
}
// NO COMPOSITOR PROCESS: composite the plugin's bitmap directly.
//
// Everything below this point routes the plugin's pixels through a TextureClient to a
// compositor, and that requires ImageBridgeChild — which only exists with off-main-thread
// composition. This embedder deliberately runs OMTC off (the offscreen renderer uses the
// in-process BasicLayerManager and hands finished frames to the browser adapter itself),
// so ImageBridgeChild::GetSingleton() is null and TextureClientRecycleAllocator is built
// around a null KnowsCompositor. The first plugin paint then dereferenced it and took the
// whole daemon down with it — upstream never sees this because the DXGI path a few
// hundred lines up checks the forwarder and the direct-bitmap path does not.
//
// A BasicLayerManager does not need a TextureClient at all: it draws an ImageLayer from
// the image's own SourceSurface. So wrap the pixels in a plain SourceSurfaceImage and
// hand that to the container.
//
// The pixels are COPIED, not wrapped. `source` above wraps the shmem the plugin drew
// into, and the plugin owns that buffer and may draw the next frame into it as soon as
// this call returns; the texture path's UpdateFromSurface copies for the same reason.
if (!ImageBridgeChild::GetSingleton()) {
RefPtr<gfx::DataSourceSurface> copy =
gfx::Factory::CreateDataSourceSurface(size, format);
if (!copy) {
NS_WARNING("Could not allocate a surface for plugin bitmap!");
return false;
}
{
gfx::DataSourceSurface::ScopedMap srcMap(source, gfx::DataSourceSurface::READ);
gfx::DataSourceSurface::ScopedMap dstMap(copy, gfx::DataSourceSurface::WRITE);
if (!srcMap.IsMapped() || !dstMap.IsMapped()) {
return false;
}
const int32_t bpp = BytesPerPixel(format);
const int32_t rowBytes = size.width * bpp;
for (int32_t y = 0; y < size.height; y++) {
memcpy(dstMap.GetData() + (ptrdiff_t)y * dstMap.GetStride(),
srcMap.GetData() + (ptrdiff_t)y * srcMap.GetStride(),
rowBytes);
}
}
RefPtr<SourceSurfaceImage> image = new SourceSurfaceImage(size, copy);
SetCurrentImage(image);
return true;
}
// Allocate a texture for the compositor.
RefPtr<TextureClientRecycleAllocator> allocator = mParent->EnsureTextureAllocatorForDirectBitmap();
RefPtr<TextureClient> texture = allocator->CreateOrRecycle(
@@ -864,6 +935,55 @@ PluginInstanceParent::RecvShowDirectDXGISurface(const WindowsHandle& handle,
}
#endif // MOZ_ENABLE_NPAPI
// Jihad: monotonic count of plugin frames that have reached the parent. Process-wide rather
// than per-instance, matching how the daemon consumes it — the embedding is single-page and the
// question it answers is "has ANY plugin produced a new frame since I last published". A plain
// uint32_t incremented and read on the same (main) thread; the daemon reads it from the same
// thread inside its tick, so no atomics are needed and none are used elsewhere in this bridge.
static uint32_t gJihadPluginFrameSeq = 0;
extern "C" {
// Weak-linked from the daemon (render/goanna/GoannaRenderPage.cpp), the same way
// jihad_offscreen_take_dirty is: an older libxul simply does not export it, and the daemon then
// falls back to its dirty-flag behaviour instead of failing to load.
MOZ_EXPORT uint32_t jihad_plugin_frame_seq(void)
{
return gJihadPluginFrameSeq;
}
}
extern "C" {
// Ask every live plugin for one frame. Returns how many were asked, so the daemon can tell "no
// plugin" from "delivered" — the same contract as jihad_plugin_palm_spotlight.
//
// WEAK on the daemon side: a libxul without this symbol keeps the child's own timer as the frame
// clock (patch 0026 behaviour), which is slower to settle but never wrong.
MOZ_EXPORT int jihad_plugin_request_frame(void)
{
#ifdef MOZ_ENABLE_NPAPI
if (!gJihadLiveInstances) {
return 0;
}
// Copy first: SendJihadRequestFrame can fail and tear the actor down, which would mutate the
// array underneath the loop. Same reasoning as the instance-list copy in
// jihad_plugin_palm_spotlight (nsPluginHost.cpp).
nsTArray<PluginInstanceParent*> snap(*gJihadLiveInstances);
int asked = 0;
for (uint32_t i = 0; i < snap.Length(); ++i) {
if (!gJihadLiveInstances->Contains(snap[i])) {
continue; // torn down by an earlier Send in this same loop
}
if (snap[i]->SendJihadRequestFrame()) {
asked++;
}
}
return asked;
#else
return 0;
#endif
}
}
bool
PluginInstanceParent::RecvShow(const NPRect& updatedRect,
const SurfaceDescriptor& newSurface,
@@ -877,6 +997,27 @@ PluginInstanceParent::RecvShow(const NPRect& updatedRect,
MOZ_ASSERT(!IsUsingDirectDrawing());
// FRAME-RATE READOUT, parent side. Paired with the child's `palm draw:` line: the child
// reports how often the plugin was ASKED to draw, this reports how many of those frames
// actually crossed the process boundary. A gap between the two numbers is the difference
// between "the plugin is slow" and "we are dropping its frames", which are opposite bugs.
{
static uint32_t sShows = 0;
static uint32_t sLastReport = 0;
sShows++;
uint32_t nowMs = uint32_t(PR_IntervalToMilliseconds(PR_IntervalNow()));
if (!sLastReport) {
sLastReport = nowMs;
} else if (nowMs - sLastReport >= 2000) {
fprintf(stderr, "[jihad-npapi] RecvShow: %u in %ums (%.1f fps)\n",
sShows, nowMs - sLastReport,
sShows * 1000.0 / double(nowMs - sLastReport));
fflush(stderr);
sShows = 0;
sLastReport = nowMs;
}
}
// XXXjwatt rewrite to use Moz2D
RefPtr<gfxASurface> surface;
if (newSurface.type() == SurfaceDescriptor::TShmem) {
@@ -959,14 +1100,75 @@ PluginInstanceParent::RecvShow(const NPRect& updatedRect,
updatedRect.bottom - updatedRect.top);
surface->MarkDirty(ur);
bool isPlugin = true;
RefPtr<gfx::SourceSurface> sourceSurface =
gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, surface, isPlugin);
RefPtr<SourceSurfaceImage> image = new SourceSurfaceImage(surface->GetSize(), sourceSurface);
// JIHAD (2026-08-09): route the legacy windowless show through the SAME
// representation the direct-bitmap path uses, for the SAME reasons.
//
// Background: the webOS npPalmDrawEvent path (PaintRectToPlatformSurface) makes Flash
// blit its stage into mCurrentSurface — measured full-magenta in the child — and ships
// it here via SendShow. The control plugin's pixels reach the screen through
// RecvShowDirectBitmap; Flash's did not, although both feed the one mImageContainer the
// BasicLayerManager reads. Two concrete differences made the legacy path invisible:
// 1. It WRAPPED the shmem (GetSourceSurfaceForSurface(nullptr,…)) instead of copying.
// The child double-buffers and SwapSurfaces() immediately after SendShow returns,
// so a wrapped front buffer is the very buffer the child repaints next — the image
// the layer later samples is racing the child. RecvShowDirectBitmap copies for
// exactly this reason ("the plugin owns that buffer and may draw the next frame
// into it as soon as this call returns").
// 2. It stamped no frameID. SetCurrentImage() on the working path assigns a monotonic
// ++mFrameID; the ImageContainer/ImageLayer treats a repeated frameID as "no new
// frame". A fixed 0 can be coalesced away.
// Copying into a fresh DataSourceSurface and stamping a monotonic frameID makes this
// path identical in substance to the one already proven to composite here.
IntSize ssize = surface->GetSize();
RefPtr<Image> image;
RefPtr<gfxImageSurface> imgSurf = surface->GetAsImageSurface();
if (imgSurf) {
// Always present the copy as B8G8R8A8, and force the alpha channel opaque when the
// source carries no alpha (RGB24 / B8G8R8X8). This is Bug 1196927 in this file's own
// words (see PluginInstanceChild::PaintRectToSurface): Cairo/Skia leave the X byte of
// a BGRX surface zeroed, and a BasicImageLayer then composites those pixels multiplied
// by alpha 0 — i.e. fully transparent. That is exactly why Flash's magenta stage
// arrived here (RecvShow logged px0=0xffff00ff) yet BasicImageLayer::Paint drew
// nothing visible, while the control plugin — which ships B8G8R8A8 — composited fine
// through the identical layer path. webOS windowless plugins are opaque
// (wmode=opaque forces the windowless instance in the first place), so forcing alpha
// opaque is correct here.
const SurfaceFormat srcFmt = surface->GetSurfaceFormat();
const bool srcHasAlpha =
srcFmt != SurfaceFormat::B8G8R8X8 &&
srcFmt != SurfaceFormat::R8G8B8X8;
RefPtr<gfx::DataSourceSurface> copy =
gfx::Factory::CreateDataSourceSurface(ssize, SurfaceFormat::B8G8R8A8);
if (copy) {
gfx::DataSourceSurface::ScopedMap dstMap(copy, gfx::DataSourceSurface::WRITE);
if (dstMap.IsMapped()) {
const int32_t rowBytes = ssize.width * 4;
for (int32_t y = 0; y < ssize.height; y++) {
uint8_t* dstRow = dstMap.GetData() + (ptrdiff_t)y * dstMap.GetStride();
memcpy(dstRow, imgSurf->Data() + (ptrdiff_t)y * imgSurf->Stride(),
rowBytes);
if (!srcHasAlpha) {
for (int32_t x = 0; x < ssize.width; x++) {
dstRow[x * 4 + 3] = 0xff; // BGRA: byte 3 is alpha
}
}
}
image = new SourceSurfaceImage(ssize, copy);
}
}
}
if (!image) {
// Fallback to the original wrap if the copy path could not be taken.
bool isPlugin = true;
RefPtr<gfx::SourceSurface> sourceSurface =
gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, surface, isPlugin);
image = new SourceSurfaceImage(ssize, sourceSurface);
}
ImageContainer::NonOwningImage holder(image);
holder.mFrameID = ++mFrameID;
AutoTArray<ImageContainer::NonOwningImage,1> imageList;
imageList.AppendElement(
ImageContainer::NonOwningImage(image));
imageList.AppendElement(holder);
ImageContainer *container = GetImageContainer();
container->SetCurrentImages(imageList);
@@ -976,6 +1178,17 @@ PluginInstanceParent::RecvShow(const NPRect& updatedRect,
}
mFrontSurface = surface;
// Jihad: count DELIVERED plugin frames so the embedder can tell a new one from a repeat.
// The daemon's only frame signal is PuppetWidget's sticky dirty boolean, which carries no
// identity: the refresh driver and ordinary page damage set the same flag, so "there is
// damage" cannot answer "did the plugin draw again". Measured 2026-08-10 on a 30 fps SWF,
// that ambiguity is what made both available policies wrong — publishing on every dirty
// tick sent ~78 card frames for ~60 plugin frames (duplicates, and 22-44 deferred because
// the adapter could not drain them), while pacing on a fixed 33 ms grid sent ~57 for ~68
// (dropped frames, so the animation stepped two positions at once). The stock webOS host
// never had to choose: it pulls the plugin synchronously inside the page paint, so it is
// 1:1 by construction. This counter is what lets the daemon be 1:1 too.
++gJihadPluginFrameSeq;
RecvNPN_InvalidateRect(updatedRect);
PLUGIN_LOG_DEBUG((" (RecvShow invalidated for surface %p)",
@@ -1301,7 +1514,11 @@ PluginInstanceParent::GetImageContainer()
return mImageContainer;
}
if (IsUsingDirectDrawing()) {
if (IsUsingDirectDrawing() && ImageBridgeChild::GetSingleton()) {
// ASYNCHRONOUS means "shared with the compositor through ImageBridge". Without an
// ImageBridge the async container silently gets no image client and never publishes
// anything, so with OMTC off this has to be an ordinary local container — which is
// what the BasicLayerManager reads from. See RecvShowDirectBitmap.
mImageContainer = LayerManager::CreateImageContainer(ImageContainer::ASYNCHRONOUS);
} else {
mImageContainer = LayerManager::CreateImageContainer();
+2
View File
@@ -117,6 +117,8 @@ typedef HWND NativeWindowHandle;
typedef XID NativeWindowHandle;
#elif defined(XP_DARWIN)
typedef intptr_t NativeWindowHandle; // never actually used, will always be 0
#elif defined(MOZ_WIDGET_HEADLESS)
typedef intptr_t NativeWindowHandle; // Jihad headless: no native window handle
#else
#error Need NativeWindowHandle for this platform
#endif
+51 -1
View File
@@ -12,6 +12,9 @@
#ifdef MOZ_WIDGET_GTK
#include <gtk/gtk.h>
#if (GTK_MAJOR_VERSION == 3)
#include <gtk/gtkx.h>
#endif
#endif
#include "nsIFile.h"
@@ -57,6 +60,9 @@ using namespace mozilla::ipc;
using namespace mozilla::plugins;
using namespace mozilla::widget;
// Defined at the bottom of this file; see the NPN SYMBOL INTERPOSITION block there.
namespace mozilla { namespace plugins { void JihadInstallNPNInterposition(); } }
#if defined(XP_WIN)
const wchar_t * kFlashFullscreenClass = L"ShockwaveFlashFullScreen";
const wchar_t * kMozillaWindowClass = L"MozillaWindowClass";
@@ -229,6 +235,10 @@ PluginModuleChild::InitForChrome(const std::string& aPluginFilename,
{
NS_ASSERTION(aChannel, "need a channel");
// Point the exported NPN_* globals at the real implementations before any plugin can be
// loaded, so a plugin that resolves them as symbols reaches us rather than libWebKitLuna.
JihadInstallNPNInterposition();
if (!InitGraphics())
return false;
@@ -248,7 +258,11 @@ PluginModuleChild::InitForChrome(const std::string& aPluginFilename,
nsPluginFile pluginFile(localFile);
nsPluginInfo info = nsPluginInfo();
if (NS_FAILED(pluginFile.GetPluginInfo(info, &mLibrary))) {
nsresult jihadRv = pluginFile.GetPluginInfo(info, &mLibrary);
fprintf(stderr, "[jihad-npapi-child] GetPluginInfo rv=0x%x lib=%d\n",
(unsigned)jihadRv, (int)!!mLibrary);
fflush(stderr);
if (NS_FAILED(jihadRv)) {
return false;
}
@@ -1101,7 +1115,11 @@ _getvalue(NPP aNPP,
return InstCast(aNPP)->NPN_GetValue(aVariable, aValue);
}
else {
#ifdef MOZ_ENABLE_NPAPI_GTK2
*(void **)aValue = xt_client_get_display();
#else
*(void **)aValue = DefaultXDisplay();
#endif
}
return NPERR_NO_ERROR;
}
@@ -1836,6 +1854,8 @@ bool
PluginModuleChild::AnswerNP_Initialize(const PluginSettings& aSettings, NPError* rv)
{
*rv = DoNP_Initialize(aSettings);
fprintf(stderr, "[jihad-npapi-child] AnswerNP_Initialize rv=%d\n", (int)*rv);
fflush(stderr);
return true;
}
@@ -1875,6 +1895,8 @@ PluginModuleChild::DoNP_Initialize(const PluginSettings& aSettings)
# error Please implement me for your platform
#endif
fprintf(stderr, "[jihad-npapi-child] DoNP_Initialize plugin returned %d\n", (int)result);
fflush(stderr);
return result;
}
@@ -2610,3 +2632,31 @@ PluginModuleChild::RecvNPP_SetValue_NPNVaudioDeviceChangeDetails(
#endif
}
#endif // MOZ_ENABLE_NPAPI
// ── NPN SYMBOL INTERPOSITION (Jihad, addons R7) ──────────────────────────────────────────
//
// The exported NPN_* globals themselves live in JihadNPNInterpose.cpp (they must, to escape
// hidden visibility — see the long comment there). All that is needed here is to point them
// at the same implementations the browser function table uses, which is done once the table
// exists. Installed from a static initializer-free helper called by the child at startup.
extern "C" {
extern void (*gJihadNPNInvalidateRect)(void*, void*);
extern void* (*gJihadNPNCreateObject)(void*, void*);
}
namespace mozilla {
namespace plugins {
void JihadInstallNPNInterposition()
{
const NPNetscapeFuncs& f = PluginModuleChild::sBrowserFuncs;
gJihadNPNInvalidateRect = (void(*)(void*, void*))f.invalidaterect;
gJihadNPNCreateObject = (void*(*)(void*, void*))f.createobject;
fprintf(stderr, "[jihad-npapi-child] NPN interposition installed invalidaterect=%p "
"createobject=%p\n",
(void*)f.invalidaterect, (void*)f.createobject);
fflush(stderr);
}
} // namespace plugins
} // namespace mozilla
+190 -1
View File
@@ -444,6 +444,8 @@ PluginModuleChromeParent::LoadModule(const char* aFilePath, uint32_t aPluginId,
parent->mSubprocess->SetCallRunnableImmediately(!parent->mIsStartingAsync);
bool launched = parent->mSubprocess->Launch(Move(onLaunchedRunnable),
aPluginTag->mSandboxLevel);
fprintf(stderr, "[jihad-npapi] LoadModule path=%s async=%d launched=%d\n",
aFilePath, (int)parent->mIsStartingAsync, (int)launched);
if (!launched) {
// We never reached open
parent->mShutdown = true;
@@ -455,7 +457,10 @@ PluginModuleChromeParent::LoadModule(const char* aFilePath, uint32_t aPluginId,
parent->mIsBlocklisted = NS_FAILED(rv) || blocklistState != 0;
if (!parent->mIsStartingAsync) {
int32_t launchTimeoutSecs = Preferences::GetInt(kLaunchTimeoutPref, 0);
if (!parent->mSubprocess->WaitUntilConnected(launchTimeoutSecs * 1000)) {
bool connected = parent->mSubprocess->WaitUntilConnected(launchTimeoutSecs * 1000);
fprintf(stderr, "[jihad-npapi] LoadModule WaitUntilConnected(%ds) = %d\n",
(int)launchTimeoutSecs, (int)connected);
if (!connected) {
parent->mShutdown = true;
return nullptr;
}
@@ -1134,9 +1139,20 @@ PluginModuleChromeParent::OnHangUIContinue()
}
#endif // XP_WIN
// Defined with the rest of the Jihad CPU-boost helpers further down this file.
namespace { void JihadCpuBoostReleaseAll(); }
void
PluginModuleParent::ActorDestroy(ActorDestroyReason why)
{
// Release the CPU boost here as well as in NPP_Destroy, because on this port NPP_Destroy is
// NOT the path a plugin usually leaves by: navigating away from a Flash page ends in the
// child's own mozalloc_abort, so the instance never gets an orderly destroy and the boost
// would leak — device-observed 2026-08-10, tunables still at 40/50000 after navigation with
// no release logged. This runs for every ActorDestroyReason, normal and abnormal, which also
// covers a plugin crash.
JihadCpuBoostReleaseAll();
switch (why) {
case AbnormalShutdown: {
mShutdown = true;
@@ -1271,6 +1287,172 @@ NP_BEGIN_MACRO \
return i->func; \
NP_END_MACRO
// ── Jihad: hold a CPU-frequency boost while a plugin instance is alive ──────────────────────
//
// WHY. The TouchPad's governor is Palm's `ondemandtcl`, whose stock `up_threshold` is 95 — it
// only raises the clock when a single core exceeds 95% load. Flash never gets there: measured on
// device, the daemon runs ~26% and plugin-container ~11% of two cores, so a passively-watched
// animation sits at the FLOOR. Sampling `scaling_cur_freq` once a second during playback gave
// 192000-384000 out of a 1188000 maximum, snapping back to 1188000 the moment the page was
// navigated away. The whole system was only 69% busy, so this was never a capacity wall.
//
// Dropping `up_threshold` to 40 and `sampling_rate` to 50000 pins 1188000 and lifts the card
// composite from 20.4-27.5 fps to 30.7-35.2, daemon paints 24.0-28.7 to 31.4-33.0, and the frame
// gap MAXIMUM — the number that reads as stutter — from 63-81 ms to 49-56. It also clears the
// audio xruns, because MP3 decode at 192 MHz underruns.
//
// NEVER WRITE `scaling_governor`. Switching away from `ondemandtcl` DEADLOCKS cpufreq in the
// kernel: every later reader of any cpufreq node blocks in unkillable D state — the daemon,
// `powerlog`, and the restore path itself — so the boost is never released and only a reboot
// clears it (and a clean `reboot` will not run, because init waits on those D-state tasks).
// Governor TUNABLE writes, which is all this does, are safe and return instantly.
//
// These are SYSTEM-WIDE tunables, so they are held only while a plugin instance exists and the
// ORIGINAL values are read back and restored on teardown. The upstart job restores them again
// from `post-stop`, because a daemon that dies holding the boost would otherwise leave the whole
// device tuned for battery burn. Both hooks run on the main thread, so the counter needs no lock.
namespace {
const char kJihadOndemandDir[] = "/sys/devices/system/cpu/cpufreq/ondemandtcl";
// The stock values, used ONLY as the restore fallback when the current value already equals what
// we are about to write — which happens when another variant's daemon is holding the boost.
// Saving the boosted value as "original" there would make the last release pin the device.
const char kJihadStockUpThreshold[] = "95";
const char kJihadStockSamplingRate[] = "200000";
// The instances that actually TOOK a boost, not a bare count. NPP_Destroy also runs for instances
// that failed before the boost was taken, and decrementing a count there would release the boost
// out from under a plugin that is still playing.
nsTArray<NPP> gJihadBoostedInstances;
bool gJihadBoostHeld = false;
char gJihadSavedUpThreshold[32];
char gJihadSavedSamplingRate[32];
bool
JihadReadTunable(const char* aName, char* aOut, size_t aOutLen)
{
char path[256];
snprintf(path, sizeof(path), "%s/%s", kJihadOndemandDir, aName);
FILE* f = fopen(path, "r");
if (!f) return false;
char* got = fgets(aOut, aOutLen, f);
fclose(f);
if (!got) return false;
// Trim the trailing newline so a value read back can be compared and rewritten verbatim.
size_t n = strlen(aOut);
while (n > 0 && (aOut[n - 1] == '\n' || aOut[n - 1] == '\r')) aOut[--n] = '\0';
return n > 0;
}
bool
JihadWriteTunable(const char* aName, const char* aValue)
{
char path[256];
snprintf(path, sizeof(path), "%s/%s", kJihadOndemandDir, aName);
FILE* f = fopen(path, "w");
if (!f) return false;
bool ok = fputs(aValue, f) >= 0;
ok = (fclose(f) == 0) && ok;
return ok;
}
// Env-tunable for the same reason the repaint divisor is: the right value is a property of the
// device under load, not of the source, and a rebuild per candidate costs a 44 MB push.
void
JihadCpuBoostTargets(const char** aUpThreshold, const char** aSamplingRate)
{
static char sUp[32] = "40";
static char sRate[32] = "50000";
static bool sInit = false;
if (!sInit) {
sInit = true;
const char* e = getenv("JIHAD_PLUGIN_CPU_UP_THRESHOLD");
if (e && *e) {
int v = atoi(e);
if (v >= 5 && v <= 95) snprintf(sUp, sizeof(sUp), "%d", v);
}
e = getenv("JIHAD_PLUGIN_CPU_SAMPLING_RATE");
if (e && *e) {
int v = atoi(e);
if (v >= 10000 && v <= 1000000) snprintf(sRate, sizeof(sRate), "%d", v);
}
}
*aUpThreshold = sUp;
*aSamplingRate = sRate;
}
bool
JihadCpuBoostEnabled()
{
const char* e = getenv("JIHAD_PLUGIN_CPU_BOOST");
return !(e && e[0] == '0' && e[1] == '\0');
}
void
JihadCpuBoostAcquire(NPP aInstance)
{
if (!JihadCpuBoostEnabled() || gJihadBoostedInstances.Contains(aInstance)) return;
gJihadBoostedInstances.AppendElement(aInstance);
if (gJihadBoostedInstances.Length() != 1 || gJihadBoostHeld) return;
const char* wantUp;
const char* wantRate;
JihadCpuBoostTargets(&wantUp, &wantRate);
if (!JihadReadTunable("up_threshold", gJihadSavedUpThreshold,
sizeof(gJihadSavedUpThreshold)) ||
!strcmp(gJihadSavedUpThreshold, wantUp)) {
strcpy(gJihadSavedUpThreshold, kJihadStockUpThreshold);
}
if (!JihadReadTunable("sampling_rate", gJihadSavedSamplingRate,
sizeof(gJihadSavedSamplingRate)) ||
!strcmp(gJihadSavedSamplingRate, wantRate)) {
strcpy(gJihadSavedSamplingRate, kJihadStockSamplingRate);
}
bool ok = JihadWriteTunable("up_threshold", wantUp);
ok = JihadWriteTunable("sampling_rate", wantRate) && ok;
gJihadBoostHeld = ok;
fprintf(stderr, "[jihad-npapi] cpu boost acquire: up_threshold %s->%s sampling_rate %s->%s%s\n",
gJihadSavedUpThreshold, wantUp, gJihadSavedSamplingRate, wantRate,
ok ? "" : " FAILED (not root, or no ondemandtcl)");
fflush(stderr);
}
void
JihadCpuBoostRelease(NPP aInstance)
{
if (!gJihadBoostedInstances.RemoveElement(aInstance)) return;
if (!gJihadBoostedInstances.IsEmpty() || !gJihadBoostHeld) return;
JihadWriteTunable("up_threshold", gJihadSavedUpThreshold);
JihadWriteTunable("sampling_rate", gJihadSavedSamplingRate);
gJihadBoostHeld = false;
fprintf(stderr, "[jihad-npapi] cpu boost release: up_threshold=%s sampling_rate=%s\n",
gJihadSavedUpThreshold, gJihadSavedSamplingRate);
fflush(stderr);
}
// Drop every outstanding boost at once. Used when the plugin module itself goes away, which on
// this port is the NORMAL exit path (see ActorDestroy), not just the crash path.
void
JihadCpuBoostReleaseAll()
{
if (gJihadBoostedInstances.IsEmpty()) return;
gJihadBoostedInstances.Clear();
if (!gJihadBoostHeld) return;
JihadWriteTunable("up_threshold", gJihadSavedUpThreshold);
JihadWriteTunable("sampling_rate", gJihadSavedSamplingRate);
gJihadBoostHeld = false;
fprintf(stderr, "[jihad-npapi] cpu boost release (module gone): up_threshold=%s sampling_rate=%s\n",
gJihadSavedUpThreshold, gJihadSavedSamplingRate);
fflush(stderr);
}
} // anonymous namespace
NPError
PluginModuleParent::NPP_Destroy(NPP instance,
NPSavedData** saved)
@@ -1296,6 +1478,7 @@ PluginModuleParent::NPP_Destroy(NPP instance,
instance->pdata = nullptr;
Unused << PluginInstanceParent::Call__delete__(parentInstance);
JihadCpuBoostRelease(instance);
return retval;
}
@@ -2292,6 +2475,12 @@ PluginModuleParent::NPP_NewInternal(NPMIMEType pluginType, NPP instance,
UpdatePluginTimeout();
// Taken ONLY here, on the single success path, and released in NPP_Destroy. Every failure
// return above this point either deletes |parentInstance| itself or hands it to NPP_Destroy,
// and a boost acquired on one of those paths would never be released — which on this device
// means leaving the WHOLE system tuned for battery burn with nothing owning it.
JihadCpuBoostAcquire(instance);
return NS_OK;
}
+5
View File
@@ -111,9 +111,14 @@ PluginProcessChild::Init()
return false;
}
fprintf(stderr, "[jihad-npapi-child] InitForChrome plugin=%s parentPid=%d\n",
pluginFilename.c_str(), (int)ParentPid());
fflush(stderr);
bool retval = mPlugin.InitForChrome(pluginFilename, ParentPid(),
IOThreadChild::message_loop(),
IOThreadChild::channel());
fprintf(stderr, "[jihad-npapi-child] InitForChrome = %d\n", (int)retval);
fflush(stderr);
#if defined(XP_MACOSX)
if (nsCocoaFeatures::OnYosemiteOrLater()) {
// Explicitly turn off CGEvent logging. This works around bug 1092855.
+9 -3
View File
@@ -88,6 +88,10 @@ UNIFIED_SOURCES += [
]
SOURCES += [
# Jihad: must NOT be unified — it deliberately includes no NPAPI headers so its exported
# NPN_* symbols escape the hidden-visibility pragma. Merging it with a TU that includes
# npapi.h would reintroduce the prior hidden declaration and silently un-export them.
'JihadNPNInterpose.cpp',
'PluginInstanceChild.cpp', # 'PluginThreadCallback' : ambiguous symbol
'PluginModuleChild.cpp', # Redefinition of mozilla::WindowsDllInterceptor sUser32Intercept
]
@@ -143,11 +147,13 @@ LOCAL_INCLUDES += [
DEFINES['FORCE_PR_LOG'] = True
if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gtk3':
CXXFLAGS += CONFIG['TK_CFLAGS']
else:
if (CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3' and
CONFIG['MOZ_ENABLE_NPAPI'] and
CONFIG['MOZ_ENABLE_NPAPI_GTK2']):
# Force build against gtk+2 for struct offsets and such.
CXXFLAGS += CONFIG['MOZ_GTK2_CFLAGS']
else:
CXXFLAGS += CONFIG['TK_CFLAGS']
CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
+1 -2
View File
@@ -34,7 +34,6 @@ interface Element : Node {
[SameObject]
readonly attribute NamedNodeMap attributes;
[Pure]
sequence<DOMString> getAttributeNames();
[Pure]
DOMString? getAttribute(DOMString name);
@@ -159,7 +158,7 @@ interface Element : Node {
* this property returns an object with computed values for grid
* tracks and lines.
*/
[ChromeOnly, Pure]
[ChromeOnly]
sequence<Grid> getGridFragments();
};
+1 -1
View File
@@ -23,7 +23,7 @@ interface HTMLElement : Element {
[CEReactions, SetterThrows, Pure]
attribute DOMString dir;
[CEReactions, GetterThrows, Pure]
[CEReactions, GetterThrows]
attribute [TreatNullAs=EmptyString] DOMString innerText;
// user interaction
+1 -1
View File
@@ -51,7 +51,7 @@ interface HTMLInputElement : HTMLElement {
attribute boolean formNoValidate;
[CEReactions, Pure, SetterThrows]
attribute DOMString formTarget;
[CEReactions, Pure, SetterThrows]
[CEReactions, SetterThrows]
attribute unsigned long height;
[Pure]
attribute boolean indeterminate;
+10
View File
@@ -5,6 +5,7 @@
// Local Includes
#include "nsDocShellTreeOwner.h"
#include "nsIBadCertListener2.h" // JIHAD: route cert errors to the embedder chrome
#include "nsWebBrowser.h"
// Helper Classes
@@ -143,6 +144,15 @@ nsDocShellTreeOwner::GetInterface(const nsIID& aIID, void** aSink)
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIBadCertListener2))) {
// JIHAD: the embedder's chrome is what implements this — see the matching comment in
// nsDocShell::GetInterface. Same forwarding shape as nsIWebBrowserChromeFocus below.
if (mWebBrowserChromeWeak != nullptr) {
return mWebBrowserChromeWeak->QueryReferent(aIID, aSink);
}
return mOwnerWin ? mOwnerWin->QueryInterface(aIID, aSink) : NS_NOINTERFACE;
}
if (aIID.Equals(NS_GET_IID(nsIWebBrowserChromeFocus))) {
if (mWebBrowserChromeWeak != nullptr) {
return mWebBrowserChromeWeak->QueryReferent(aIID, aSink);
+36 -3
View File
@@ -390,6 +390,14 @@ nsWebBrowserFind::SetSelectionAndScroll(nsPIDOMWindowOuter* aWindow,
nsCOMPtr<nsISelection> selection;
// JIHAD: frame->GetSelectionController can leave selCon NULL, and this dereferenced it
// unconditionally — a null deref that took the whole process down. It is reachable in an
// offscreen embedding with no chrome: this is the ONLY thing that made find-in-page
// unusable there (faultaddr=0x0, measured repeatedly). Guarding costs nothing and the
// rest of the function already tolerates a null `selection`.
if (!selCon) {
return;
}
selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
getter_AddRefs(selection));
@@ -707,7 +715,24 @@ nsWebBrowserFind::SearchInFrame(nsPIDOMWindowOuter* aWindow, bool aWrapping,
return NS_ERROR_FAILURE;
}
if (!nsContentUtils::SubjectPrincipal()->Subsumes(theDoc->NodePrincipal())) {
// JIHAD: this same-origin check is why find-in-page took the whole process down in this
// embedding, and the engine says why itself. nsContentUtils::SubjectPrincipal() begins:
// JSContext* cx = GetCurrentJSContext();
// if (!cx) {
// MOZ_CRASH("Accessing the Subject Principal without an AutoJSAPI on the stack is forbidden");
// }
// An EMBEDDER calls nsIWebBrowserFind::FindNext from C++ with no script on the stack, so
// there is no JSContext and MOZ_CRASH fires — a deliberate abort that presents as SIGSEGV at
// address 0, which is precisely the fault this port recorded for two weeks and attributed to
// "a frame-selection controller the offscreen browser doesn't set up". That was wrong: the
// selection machinery is fine and the crash happens BEFORE any of it, on the security check.
//
// The check is meaningful only when there IS a caller to check. With no JS on the stack the
// caller is native embedding code, which is already fully trusted — it is inside libxul's own
// process, holding the nsIWebBrowserFind for that very docShell. So: consult the subject
// principal only when a JSContext exists, and otherwise proceed.
if (nsContentUtils::GetCurrentJSContext() &&
!nsContentUtils::SubjectPrincipal()->Subsumes(theDoc->NodePrincipal())) {
return NS_ERROR_DOM_PROP_ACCESS_DENIED;
}
@@ -809,8 +834,11 @@ nsWebBrowserFind::GetFrameSelection(nsPIDOMWindowOuter* aWindow)
nsCOMPtr<nsISelection> sel;
if (frame) {
frame->GetSelectionController(presContext, getter_AddRefs(selCon));
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
getter_AddRefs(sel));
// JIHAD: same unguarded deref as above — GetSelectionController can yield null.
if (selCon) {
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
getter_AddRefs(sel));
}
if (sel) {
int32_t count = -1;
sel->GetRangeCount(&count);
@@ -820,7 +848,12 @@ nsWebBrowserFind::GetFrameSelection(nsPIDOMWindowOuter* aWindow)
}
}
// JIHAD: and the fallback QI is not guaranteed either — if the presShell does not answer
// nsISelectionController we must return nothing rather than crash.
selCon = do_QueryInterface(presShell);
if (!selCon) {
return nullptr;
}
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
getter_AddRefs(sel));
return sel.forget();
+2 -1
View File
@@ -12,5 +12,6 @@ if CONFIG['NS_PRINTING']:
DIRS += ['win']
elif toolkit == 'cocoa':
DIRS += ['mac']
elif CONFIG['MOZ_PDF_PRINTING']:
elif CONFIG['MOZ_PDF_PRINTING'] or toolkit == 'headless':
# Jihad headless: reuse the gtk-free PDF printing prompt service.
DIRS += ['unixshared']
+1 -1
View File
@@ -1374,7 +1374,7 @@ public:
static already_AddRefed<ScaledFont>
CreateScaledFontForNativeFont(const NativeFont &aNativeFont, Float aSize);
#ifdef MOZ_WIDGET_GTK
#if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_HEADLESS)
static already_AddRefed<ScaledFont>
CreateScaledFontForFontconfigFont(cairo_scaled_font_t* aScaledFont, FcPattern* aPattern, Float aSize);
#endif
+2 -2
View File
@@ -30,7 +30,7 @@
#include "NativeFontResourceMac.h"
#endif
#ifdef MOZ_WIDGET_GTK
#if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_HEADLESS)
#include "ScaledFontFontconfig.h"
#endif
@@ -584,7 +584,7 @@ Factory::CreateScaledFontWithCairo(const NativeFont& aNativeFont, Float aSize, c
#endif
}
#ifdef MOZ_WIDGET_GTK
#if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_HEADLESS)
already_AddRefed<ScaledFont>
Factory::CreateScaledFontForFontconfigFont(cairo_scaled_font_t* aScaledFont, FcPattern* aPattern, Float aSize)
{
+3 -3
View File
@@ -91,7 +91,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'windows':
'JobScheduler_posix.cpp',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3'):
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3', 'headless'):
SOURCES += [
'ScaledFontFontconfig.cpp',
]
@@ -209,12 +209,12 @@ FINAL_LIBRARY = 'xul'
for var in ('USE_CAIRO', 'MOZ2D_HAS_MOZ_CAIRO'):
DEFINES[var] = True
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3'):
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3', 'headless'):
DEFINES['MOZ_ENABLE_FREETYPE'] = True
CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3'):
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3', 'headless'):
CXXFLAGS += CONFIG['CAIRO_FT_CFLAGS']
LOCAL_INCLUDES += CONFIG['SKIA_INCLUDES']
+120 -105
View File
@@ -805,6 +805,10 @@ cairo_cff_font_read_cid_fontdict (cairo_cff_font_t *font, unsigned char *ptr)
}
operand = decode_integer (operand, &size);
decode_integer (operand, &offset);
if (unlikely (offset < 0 || (unsigned long)offset > font->data_length)) {
status = CAIRO_INT_STATUS_UNSUPPORTED;
goto fail;
}
status = cff_dict_init (&font->fd_private_dict[i]);
if (unlikely (status))
goto fail;
@@ -866,6 +870,8 @@ cairo_cff_font_read_top_dict (cairo_cff_font_t *font)
operand = cff_dict_get_operands (font->top_dict, CHARSTRINGS_OP, &size);
decode_integer (operand, &offset);
p = font->data + offset;
if (unlikely (p < font->data || p > font->data_end))
return CAIRO_INT_STATUS_UNSUPPORTED;
status = cff_index_read (&font->charstrings_index, &p, font->data_end);
if (unlikely (status))
goto fail;
@@ -874,49 +880,58 @@ cairo_cff_font_read_top_dict (cairo_cff_font_t *font)
if (font->is_cid) {
operand = cff_dict_get_operands (font->top_dict, FDSELECT_OP, &size);
decode_integer (operand, &offset);
status = cairo_cff_font_read_fdselect (font, font->data + offset);
if (unlikely (status))
goto fail;
p = font->data + offset;
if (unlikely (p < font->data || p > font->data_end))
return CAIRO_INT_STATUS_UNSUPPORTED;
status = cairo_cff_font_read_fdselect (font, p);
if (unlikely (status))
goto fail;
operand = cff_dict_get_operands (font->top_dict, FDARRAY_OP, &size);
decode_integer (operand, &offset);
status = cairo_cff_font_read_cid_fontdict (font, font->data + offset);
if (unlikely (status))
goto fail;
p = font->data + offset;
if (unlikely (p < font->data || p > font->data_end))
return CAIRO_INT_STATUS_UNSUPPORTED;
status = cairo_cff_font_read_cid_fontdict (font, p);
if (unlikely (status))
goto fail;
} else {
operand = cff_dict_get_operands (font->top_dict, PRIVATE_OP, &size);
operand = decode_integer (operand, &size);
decode_integer (operand, &offset);
p = font->data + offset;
if (unlikely (p < font->data || p > font->data_end))
return CAIRO_INT_STATUS_UNSUPPORTED;
status = cairo_cff_font_read_private_dict (font,
font->private_dict,
&font->local_sub_index,
font->data + offset,
size);
if (unlikely (status))
goto fail;
&font->local_sub_index,
p,
size);
if (unlikely (status))
goto fail;
}
/* Use maximum sized encoding to reserve space for later modification. */
end_buf = encode_integer_max (buf, 0);
status = cff_dict_set_operands (font->top_dict,
CHARSTRINGS_OP, buf, end_buf - buf);
CHARSTRINGS_OP, buf, end_buf - buf);
if (unlikely (status))
goto fail;
goto fail;
status = cff_dict_set_operands (font->top_dict,
FDSELECT_OP, buf, end_buf - buf);
FDSELECT_OP, buf, end_buf - buf);
if (unlikely (status))
goto fail;
goto fail;
status = cff_dict_set_operands (font->top_dict,
FDARRAY_OP, buf, end_buf - buf);
FDARRAY_OP, buf, end_buf - buf);
if (unlikely (status))
goto fail;
goto fail;
status = cff_dict_set_operands (font->top_dict,
CHARSET_OP, buf, end_buf - buf);
CHARSET_OP, buf, end_buf - buf);
if (unlikely (status))
goto fail;
goto fail;
cff_dict_remove (font->top_dict, ENCODING_OP);
cff_dict_remove (font->top_dict, PRIVATE_OP);
@@ -985,26 +1000,26 @@ cairo_cff_font_set_ros_strings (cairo_cff_font_t *font)
(unsigned char *)registry,
strlen(registry));
if (unlikely (status))
return status;
return status;
sid2 = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
status = cff_index_append_copy (&font->strings_subset_index,
(unsigned char *)ordering,
strlen(ordering));
strlen(ordering));
if (unlikely (status))
return status;
return status;
p = encode_integer (buf, sid1);
p = encode_integer (p, sid2);
p = encode_integer (p, 0);
status = cff_dict_set_operands (font->top_dict, ROS_OP, buf, p - buf);
if (unlikely (status))
return status;
return status;
p = encode_integer (buf, font->scaled_font_subset->num_glyphs);
status = cff_dict_set_operands (font->top_dict, CIDCOUNT_OP, buf, p - buf);
if (unlikely (status))
return status;
return status;
return CAIRO_STATUS_SUCCESS;
}
@@ -1038,7 +1053,7 @@ cairo_cff_font_subset_dict_string(cairo_cff_font_t *font,
p = encode_integer (buf, sid);
status = cff_dict_set_operands (dict, operator, buf, p - buf);
if (unlikely (status))
return status;
return status;
return CAIRO_STATUS_SUCCESS;
}
@@ -1101,19 +1116,19 @@ cairo_cff_font_subset_fontdict (cairo_cff_font_t *font)
font->fdselect_subset = calloc (font->scaled_font_subset->num_glyphs,
sizeof (int));
if (unlikely (font->fdselect_subset == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
font->fd_subset_map = calloc (font->num_fontdicts, sizeof (int));
if (unlikely (font->fd_subset_map == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
font->private_dict_offset = calloc (font->num_fontdicts, sizeof (int));
if (unlikely (font->private_dict_offset == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
reverse_map = calloc (font->num_fontdicts, sizeof (int));
if (unlikely (reverse_map == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
for (i = 0; i < font->num_fontdicts; i++)
reverse_map[i] = -1;
@@ -1143,22 +1158,22 @@ cairo_cff_font_create_cid_fontdict (cairo_cff_font_t *font)
font->num_fontdicts = 1;
font->fd_dict = malloc (sizeof (cairo_hash_table_t *));
if (unlikely (font->fd_dict == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
if (cff_dict_init (&font->fd_dict[0])) {
free (font->fd_dict);
font->fd_dict = NULL;
font->num_fontdicts = 0;
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
free (font->fd_dict);
font->fd_dict = NULL;
font->num_fontdicts = 0;
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
font->fd_subset_map = malloc (sizeof (int));
if (unlikely (font->fd_subset_map == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
font->private_dict_offset = malloc (sizeof (int));
if (unlikely (font->private_dict_offset == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
font->fd_subset_map[0] = 0;
font->num_subset_fontdicts = 1;
@@ -1169,7 +1184,7 @@ cairo_cff_font_create_cid_fontdict (cairo_cff_font_t *font)
end_buf = encode_integer_max (end_buf, 0);
status = cff_dict_set_operands (font->fd_dict[0], PRIVATE_OP, buf, end_buf - buf);
if (unlikely (status))
return status;
return status;
return CAIRO_STATUS_SUCCESS;
}
@@ -1208,7 +1223,7 @@ cairo_cff_font_subset_font (cairo_cff_font_t *font)
status = cairo_cff_font_set_ros_strings (font);
if (unlikely (status))
return status;
return status;
status = cairo_cff_font_subset_charstrings (font);
if (unlikely (status))
@@ -1219,7 +1234,7 @@ cairo_cff_font_subset_font (cairo_cff_font_t *font)
else
status = cairo_cff_font_create_cid_fontdict (font);
if (unlikely (status))
return status;
return status;
status = cairo_cff_font_subset_strings (font);
if (unlikely (status))
@@ -1271,7 +1286,7 @@ cairo_cff_font_write_name (cairo_cff_font_t *font)
(unsigned char *) font->subset_font_name,
strlen(font->subset_font_name));
if (unlikely (status))
goto FAIL;
goto FAIL;
status = cff_index_write (&index, &font->output);
if (unlikely (status))
@@ -1464,9 +1479,9 @@ cairo_cff_font_write_cid_fontdict (cairo_cff_font_t *font)
if (unlikely (status))
return status;
offset_array_ptr = (uint32_t *) _cairo_array_index (&font->output, offset_array);
offset_array_ptr = (uint32_t *) _cairo_array_index (&font->output, offset_array);
*offset_array_ptr = cpu_to_be32(_cairo_array_num_elements (&font->output) - offset_base);
offset_array += sizeof(uint32_t);
offset_array += sizeof(uint32_t);
}
return CAIRO_STATUS_SUCCESS;
@@ -1566,15 +1581,15 @@ cairo_cff_font_write_cid_private_dict_and_local_sub (cairo_cff_font_t *font)
0,
font->fd_dict[0],
font->private_dict);
if (unlikely (status))
return status;
if (unlikely (status))
return status;
status = cairo_cff_font_write_local_sub (font,
0,
font->private_dict,
&font->local_sub_index);
if (unlikely (status))
return status;
if (unlikely (status))
return status;
}
return CAIRO_STATUS_SUCCESS;
@@ -1698,7 +1713,7 @@ _cairo_cff_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
backend = scaled_font_subset->scaled_font->backend;
if (!backend->load_truetype_table)
return CAIRO_INT_STATUS_UNSUPPORTED;
return CAIRO_INT_STATUS_UNSUPPORTED;
data_length = 0;
status = backend->load_truetype_table( scaled_font_subset->scaled_font,
@@ -1736,12 +1751,12 @@ _cairo_cff_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
_cairo_array_init (&font->output, sizeof (char));
status = _cairo_array_grow_by (&font->output, 4096);
if (unlikely (status))
goto fail2;
goto fail2;
font->subset_font_name = strdup (subset_name);
if (unlikely (font->subset_font_name == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail2;
goto fail2;
}
font->x_min = (int16_t) be16_to_cpu (head.x_min);
font->y_min = (int16_t) be16_to_cpu (head.y_min);
@@ -1755,18 +1770,18 @@ _cairo_cff_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
font->font_name = NULL;
status = _cairo_truetype_read_font_name (scaled_font_subset->scaled_font,
&font->ps_name,
&font->font_name);
&font->ps_name,
&font->font_name);
if (_cairo_status_is_error (status))
goto fail3;
goto fail3;
/* If the PS name is not found, create a CairoFont-x-y name. */
if (font->ps_name == NULL) {
font->ps_name = malloc (30);
if (unlikely (font->ps_name == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail3;
}
}
snprintf(font->ps_name, 30, "CairoFont-%u-%u",
scaled_font_subset->font_id,
@@ -1781,7 +1796,7 @@ _cairo_cff_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
status = cairo_cff_font_create_set_widths (font);
if (unlikely (status))
goto fail5;
goto fail5;
font->data_length = data_length;
font->data = malloc (data_length);
@@ -1799,11 +1814,11 @@ _cairo_cff_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
status = cff_dict_init (&font->top_dict);
if (unlikely (status))
goto fail6;
goto fail6;
status = cff_dict_init (&font->private_dict);
if (unlikely (status))
goto fail7;
goto fail7;
cff_index_init (&font->strings_index);
cff_index_init (&font->charstrings_index);
@@ -1831,7 +1846,7 @@ fail5:
free (font->widths);
fail4:
if (font->font_name)
free (font->font_name);
free (font->font_name);
fail3:
free (font->subset_font_name);
fail2:
@@ -1848,7 +1863,7 @@ cairo_cff_font_destroy (cairo_cff_font_t *font)
free (font->widths);
if (font->font_name)
free (font->font_name);
free (font->font_name);
free (font->ps_name);
free (font->subset_font_name);
_cairo_array_fini (&font->output);
@@ -1902,7 +1917,7 @@ cairo_cff_font_destroy (cairo_cff_font_t *font)
cairo_status_t
_cairo_cff_subset_init (cairo_cff_subset_t *cff_subset,
const char *subset_name,
const char *subset_name,
cairo_scaled_font_subset_t *font_subset)
{
cairo_cff_font_t *font = NULL; /* squelch bogus compiler warning */
@@ -1913,32 +1928,32 @@ _cairo_cff_subset_init (cairo_cff_subset_t *cff_subset,
status = _cairo_cff_font_create (font_subset, &font, subset_name);
if (unlikely (status))
return status;
return status;
status = cairo_cff_font_generate (font, &data, &length);
if (unlikely (status))
goto fail1;
goto fail1;
cff_subset->ps_name = strdup (font->ps_name);
if (unlikely (cff_subset->ps_name == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail1;
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail1;
}
if (font->font_name) {
cff_subset->font_name = strdup (font->font_name);
if (cff_subset->font_name == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail2;
}
cff_subset->font_name = strdup (font->font_name);
if (cff_subset->font_name == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail2;
}
} else {
cff_subset->font_name = NULL;
cff_subset->font_name = NULL;
}
cff_subset->widths = calloc (sizeof (double), font->scaled_font_subset->num_glyphs);
if (unlikely (cff_subset->widths == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail3;
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail3;
}
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
cff_subset->widths[i] = (double)font->widths[i]/font->units_per_em;
@@ -1952,8 +1967,8 @@ _cairo_cff_subset_init (cairo_cff_subset_t *cff_subset,
cff_subset->data = malloc (length);
if (unlikely (cff_subset->data == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail4;
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail4;
}
memcpy (cff_subset->data, data, length);
@@ -1967,7 +1982,7 @@ _cairo_cff_subset_init (cairo_cff_subset_t *cff_subset,
free (cff_subset->widths);
fail3:
if (cff_subset->font_name)
free (cff_subset->font_name);
free (cff_subset->font_name);
fail2:
free (cff_subset->ps_name);
fail1:
@@ -1981,7 +1996,7 @@ _cairo_cff_subset_fini (cairo_cff_subset_t *subset)
{
free (subset->ps_name);
if (subset->font_name)
free (subset->font_name);
free (subset->font_name);
free (subset->widths);
free (subset->data);
}
@@ -1996,7 +2011,7 @@ _cairo_cff_font_fallback_create (cairo_scaled_font_subset_t *scaled_font_subset
font = calloc (1, sizeof (cairo_cff_font_t));
if (unlikely (font == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
font->backend = NULL;
font->scaled_font_subset = scaled_font_subset;
@@ -2004,18 +2019,18 @@ _cairo_cff_font_fallback_create (cairo_scaled_font_subset_t *scaled_font_subset
_cairo_array_init (&font->output, sizeof (char));
status = _cairo_array_grow_by (&font->output, 4096);
if (unlikely (status))
goto fail1;
goto fail1;
font->subset_font_name = strdup (subset_name);
if (unlikely (font->subset_font_name == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail1;
goto fail1;
}
font->ps_name = strdup (subset_name);
if (unlikely (font->ps_name == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail2;
goto fail2;
}
font->font_name = NULL;
@@ -2038,11 +2053,11 @@ _cairo_cff_font_fallback_create (cairo_scaled_font_subset_t *scaled_font_subset
status = cff_dict_init (&font->top_dict);
if (unlikely (status))
goto fail4;
goto fail4;
status = cff_dict_init (&font->private_dict);
if (unlikely (status))
goto fail5;
goto fail5;
cff_index_init (&font->strings_index);
cff_index_init (&font->charstrings_index);
@@ -2068,7 +2083,7 @@ fail4:
free (font->widths);
fail3:
if (font->font_name)
free (font->font_name);
free (font->font_name);
free (font->ps_name);
fail2:
free (font->subset_font_name);
@@ -2105,39 +2120,39 @@ cairo_cff_font_fallback_generate (cairo_cff_font_t *font,
end_buf = encode_integer (end_buf, type2_subset->x_max);
end_buf = encode_integer (end_buf, type2_subset->y_max);
status = cff_dict_set_operands (font->top_dict,
FONTBBOX_OP, buf, end_buf - buf);
FONTBBOX_OP, buf, end_buf - buf);
if (unlikely (status))
return status;
return status;
end_buf = encode_integer_max (buf, 0);
status = cff_dict_set_operands (font->top_dict,
CHARSTRINGS_OP, buf, end_buf - buf);
CHARSTRINGS_OP, buf, end_buf - buf);
if (unlikely (status))
return status;
return status;
status = cff_dict_set_operands (font->top_dict,
FDSELECT_OP, buf, end_buf - buf);
FDSELECT_OP, buf, end_buf - buf);
if (unlikely (status))
return status;
return status;
status = cff_dict_set_operands (font->top_dict,
FDARRAY_OP, buf, end_buf - buf);
FDARRAY_OP, buf, end_buf - buf);
if (unlikely (status))
return status;
return status;
status = cff_dict_set_operands (font->top_dict,
CHARSET_OP, buf, end_buf - buf);
CHARSET_OP, buf, end_buf - buf);
if (unlikely (status))
return status;
return status;
status = cairo_cff_font_set_ros_strings (font);
if (unlikely (status))
return status;
return status;
/* Create CID FD dictionary */
status = cairo_cff_font_create_cid_fontdict (font);
if (unlikely (status))
return status;
return status;
/* Create charstrings */
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
@@ -2163,7 +2178,7 @@ cairo_cff_font_fallback_generate (cairo_cff_font_t *font,
cairo_status_t
_cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset,
const char *subset_name,
const char *subset_name,
cairo_scaled_font_subset_t *font_subset)
{
cairo_cff_font_t *font = NULL; /* squelch bogus compiler warning */
@@ -2175,27 +2190,27 @@ _cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset,
status = _cairo_cff_font_fallback_create (font_subset, &font, subset_name);
if (unlikely (status))
return status;
return status;
status = _cairo_type2_charstrings_init (&type2_subset, font_subset);
if (unlikely (status))
goto fail1;
goto fail1;
status = cairo_cff_font_fallback_generate (font, &type2_subset, &data, &length);
if (unlikely (status))
goto fail2;
goto fail2;
cff_subset->font_name = NULL;
cff_subset->ps_name = strdup (font->ps_name);
if (unlikely (cff_subset->ps_name == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail2;
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail2;
}
cff_subset->widths = calloc (sizeof (double), font->scaled_font_subset->num_glyphs);
if (unlikely (cff_subset->widths == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail3;
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail3;
}
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
@@ -2210,8 +2225,8 @@ _cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset,
cff_subset->data = malloc (length);
if (unlikely (cff_subset->data == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail4;
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail4;
}
memcpy (cff_subset->data, data, length);
+10 -3
View File
@@ -87,12 +87,19 @@ public:
bool
BasicPlanarYCbCrImage::CopyData(const Data& aData)
{
RecyclingPlanarYCbCrImage::CopyData(aData);
if (mDelayedConversion) {
if (!RecyclingPlanarYCbCrImage::CopyData(aData)) {
return false;
}
// The YCbCr copy above succeeded; delaying the RGB conversion is not a
// failure. GetAsSourceSurface() converts on demand when mDecodedBuffer is
// null. Returning false here made VideoData::CreateAndCopyData report OOM
// (MEDIA_ERR_DECODE) for any frame decoded while BasicImageLayer::Paint had
// swapped this factory into the video's ImageContainer.
if (mDelayedConversion) {
return true;
}
// Do some sanity checks to prevent integer overflow
if (aData.mYSize.width > PlanarYCbCrImage::MAX_DIMENSION ||
aData.mYSize.height > PlanarYCbCrImage::MAX_DIMENSION) {
+3 -2
View File
@@ -529,7 +529,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] in {'cocoa', 'uikit'}:
SOURCES += [
'skia/src/ports/SkFontHost_mac.cpp',
]
if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT'] or CONFIG['MOZ_WIDGET_TOOLKIT'] == 'headless':
UNIFIED_SOURCES += [
'skia/src/ports/SkDebug_stdio.cpp',
'skia/src/ports/SkOSFile_posix.cpp',
@@ -665,6 +665,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] in {
'cocoa',
'gtk2',
'gtk3',
'headless',
'uikit',
}:
DEFINES['SK_FONTHOST_DOES_NOT_USE_FONTMGR'] = 1
@@ -738,7 +739,7 @@ if CONFIG['CLANG_CXX'] or CONFIG['CLANG_CL']:
'-Wno-unused-private-field',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3'):
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3', 'headless'):
CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
CXXFLAGS += CONFIG['CAIRO_FT_CFLAGS']
+7
View File
@@ -32,6 +32,9 @@
#include <gdk/gdk.h>
#include "gfxPlatformGtk.h"
#endif
#ifdef MOZ_WIDGET_HEADLESS
#include "gfxPlatformHeadless.h"
#endif
#ifdef MOZ_X11
#include "mozilla/X11Util.h"
@@ -1764,7 +1767,11 @@ gfxFcPlatformFontList::FindGenericFamilies(const nsAString& aGeneric,
// -- select the fonts to be used for the generic
prefFonts = new PrefFontList; // can be empty but in practice won't happen
#ifdef MOZ_WIDGET_HEADLESS
uint32_t limit = gfxPlatformHeadless::GetPlatform()->MaxGenericSubstitions();
#else
uint32_t limit = gfxPlatformGtk::GetPlatform()->MaxGenericSubstitions();
#endif
bool foundFontWithLang = false;
for (int i = 0; i < faces->nfont; i++) {
FcPattern* font = faces->fonts[i];
+11
View File
@@ -40,6 +40,8 @@
#elif defined(XP_MACOSX)
#include "gfxPlatformMac.h"
#include "gfxQuartzSurface.h"
#elif defined(MOZ_WIDGET_HEADLESS)
#include "gfxPlatformHeadless.h"
#elif defined(MOZ_WIDGET_GTK)
#include "gfxPlatformGtk.h"
#elif defined(ANDROID)
@@ -572,6 +574,8 @@ gfxPlatform::Init()
gPlatform = new gfxWindowsPlatform;
#elif defined(XP_MACOSX)
gPlatform = new gfxPlatformMac;
#elif defined(MOZ_WIDGET_HEADLESS)
gPlatform = new gfxPlatformHeadless;
#elif defined(MOZ_WIDGET_GTK)
gPlatform = new gfxPlatformGtk;
#elif defined(ANDROID)
@@ -2166,6 +2170,13 @@ gfxPlatform::UsesOffMainThreadCompositing()
result |= gfxPrefs::LayersAccelerationForceEnabledDoNotUseDirectly();
#endif
// Jihad Browser: the headless BrowserServer embedder has no compositor
// process; allow forcing off-main-thread compositing off (use the in-process
// BasicLayerManager) via env, since the gfxPrefs "Once" snapshot can miss a
// grepref set during XRE_InitEmbedding2 init ordering.
if (getenv("JIHAD_DISABLE_OMTC")) {
result = false;
}
firstTime = false;
}
+15 -3
View File
@@ -72,7 +72,17 @@ static cairo_user_data_key_t cairo_gdk_drawable_key;
gfxPlatformGtk::gfxPlatformGtk()
{
gtk_init(nullptr, nullptr);
// Jihad: in JIHAD_OFFSCREEN (headless daemon) mode there is no X server on the
// device. gtk_init() calls exit() if it cannot open a display; gtk_init_check()
// returns false instead and leaves GTK usable for the non-X paths (fontconfig/
// freetype font list, image/CPU surfaces via the BasicLayerManager). The X code
// below is already guarded by GDK_IS_X11_DISPLAY(gdk_display_get_default()),
// which is false with no display, so it is skipped cleanly.
if (getenv("JIHAD_OFFSCREEN")) {
gtk_init_check(nullptr, nullptr);
} else {
gtk_init(nullptr, nullptr);
}
mMaxGenericSubstitutions = UNINITIALIZED_VALUE;
@@ -325,8 +335,10 @@ gfxPlatformGtk::GetDPI()
if (!sDPI) {
// Make sure init is run so we have a resolution
GdkScreen *screen = gdk_screen_get_default();
gtk_settings_get_for_screen(screen);
sDPI = int32_t(round(gdk_screen_get_resolution(screen)));
if (screen) { // null when headless (no X display)
gtk_settings_get_for_screen(screen);
sDPI = int32_t(round(gdk_screen_get_resolution(screen)));
}
if (sDPI <= 0) {
// Fall back to something sane
sDPI = 96;
+834
View File
@@ -0,0 +1,834 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#define PANGO_ENABLE_BACKEND
#define PANGO_ENABLE_ENGINE
#include "gfxPlatformHeadless.h"
#include "prenv.h"
#include "nsUnicharUtils.h"
#include "nsUnicodeProperties.h"
#include "gfx2DGlue.h"
#include "gfxFcPlatformFontList.h"
#include "gfxConfig.h"
#include "gfxContext.h"
#include "gfxUserFontSet.h"
#include "gfxUtils.h"
#include "gfxFT2FontBase.h"
#include "gfxPrefs.h"
#include "gfxTextRun.h"
#include "VsyncSource.h"
#include "mozilla/Atomics.h"
#include "mozilla/Monitor.h"
#include "base/task.h"
#include "base/thread.h"
#include "base/message_loop.h"
#include "mozilla/gfx/Logging.h"
#include "mozilla/gfx/2D.h"
#include "cairo.h"
#include "gfxImageSurface.h"
#include "mozilla/Preferences.h"
#ifdef MOZ_X11
#include "gfxXlibSurface.h"
#include "cairo-xlib.h"
#include "mozilla/X11Util.h"
#ifdef GL_PROVIDER_GLX
#include "GLContextProvider.h"
#include "GLContextGLX.h"
#include "GLXLibrary.h"
#endif
/* Undefine the Status from Xlib since it will conflict with system headers on OSX */
#if defined(__APPLE__) && defined(Status)
#undef Status
#endif
#endif /* MOZ_X11 */
#include <fontconfig/fontconfig.h>
#include "nsMathUtils.h"
#define GDK_PIXMAP_SIZE_MAX 32767
#define GFX_PREF_MAX_GENERIC_SUBSTITUTIONS "gfx.font_rendering.fontconfig.max_generic_substitutions"
using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::unicode;
#if (MOZ_WIDGET_GTK == 2)
static cairo_user_data_key_t cairo_gdk_drawable_key;
#endif
gfxPlatformHeadless::gfxPlatformHeadless()
{
// Jihad: in JIHAD_OFFSCREEN (headless daemon) mode there is no X server on the
// device. gtk_init() calls exit() if it cannot open a display; gtk_init_check()
// returns false instead and leaves GTK usable for the non-X paths (fontconfig/
// freetype font list, image/CPU surfaces via the BasicLayerManager). The X code
// below is already guarded by GDK_IS_X11_DISPLAY(gdk_display_get_default()),
// which is false with no display, so it is skipped cleanly.
/* headless: no gtk_init */
mMaxGenericSubstitutions = UNINITIALIZED_VALUE;
#ifdef MOZ_X11
if (XRE_IsParentProcess()) {
if (GDK_IS_X11_DISPLAY(gdk_display_get_default()) &&
mozilla::Preferences::GetBool("gfx.xrender.enabled"))
{
gfxVars::SetUseXRender(true);
}
}
#endif
uint32_t canvasMask = BackendTypeBit(BackendType::CAIRO);
uint32_t contentMask = BackendTypeBit(BackendType::CAIRO);
#ifdef USE_SKIA
canvasMask |= BackendTypeBit(BackendType::SKIA);
contentMask |= BackendTypeBit(BackendType::SKIA);
#endif
InitBackendPrefs(canvasMask, BackendType::CAIRO,
contentMask, BackendType::CAIRO);
#ifdef MOZ_X11
if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) {
mCompositorDisplay = XOpenDisplay(nullptr);
MOZ_ASSERT(mCompositorDisplay, "Failed to create compositor display!");
} else {
mCompositorDisplay = nullptr;
}
#endif // MOZ_X11
}
gfxPlatformHeadless::~gfxPlatformHeadless()
{
#ifdef MOZ_X11
if (mCompositorDisplay) {
XCloseDisplay(mCompositorDisplay);
}
#endif // MOZ_X11
}
void
gfxPlatformHeadless::FlushContentDrawing()
{
#ifdef MOZ_X11
if (gfxVars::UseXRender()) {
XFlush(DefaultXDisplay());
}
#endif
}
already_AddRefed<gfxASurface>
gfxPlatformHeadless::CreateOffscreenSurface(const IntSize& aSize,
gfxImageFormat aFormat)
{
if (!Factory::AllowedSurfaceSize(aSize)) {
return nullptr;
}
RefPtr<gfxASurface> newSurface;
bool needsClear = true;
#ifdef MOZ_X11
// XXX we really need a different interface here, something that passes
// in more context, including the display and/or target surface type that
// we should try to match
GdkScreen *gdkScreen = gdk_screen_get_default();
if (gdkScreen) {
// When forcing PaintedLayers to use image surfaces for content,
// force creation of gfxImageSurface surfaces.
if (gfxVars::UseXRender()) {
Screen *screen = gdk_x11_screen_get_xscreen(gdkScreen);
XRenderPictFormat* xrenderFormat =
gfxXlibSurface::FindRenderFormat(DisplayOfScreen(screen),
aFormat);
if (xrenderFormat) {
newSurface = gfxXlibSurface::Create(screen, xrenderFormat,
aSize);
}
}
}
#endif
if (!newSurface) {
// We couldn't create a native surface for whatever reason;
// e.g., no display, no RENDER, bad size, etc.
// Fall back to image surface for the data.
newSurface = new gfxImageSurface(aSize, aFormat);
// The gfxImageSurface ctor zeroes this for us, no need to
// waste time clearing again
needsClear = false;
}
if (newSurface->CairoStatus()) {
newSurface = nullptr; // surface isn't valid for some reason
}
if (newSurface && needsClear) {
gfxUtils::ClearThebesSurface(newSurface);
}
return newSurface.forget();
}
nsresult
gfxPlatformHeadless::GetFontList(nsIAtom *aLangGroup,
const nsACString& aGenericFamily,
nsTArray<nsString>& aListOfFonts)
{
gfxPlatformFontList::PlatformFontList()->GetFontList(aLangGroup,
aGenericFamily,
aListOfFonts);
return NS_OK;
}
nsresult
gfxPlatformHeadless::UpdateFontList()
{
gfxPlatformFontList::PlatformFontList()->UpdateFontList();
return NS_OK;
}
// xxx - this is ubuntu centric, need to go through other distros and flesh
// out a more general list
static const char kFontDejaVuSans[] = "DejaVu Sans";
static const char kFontDejaVuSerif[] = "DejaVu Serif";
static const char kFontFreeSans[] = "FreeSans";
static const char kFontFreeSerif[] = "FreeSerif";
static const char kFontTakaoPGothic[] = "TakaoPGothic";
static const char kFontTwemojiMozilla[] = "Twemoji Mozilla";
static const char kFontDroidSansFallback[] = "Droid Sans Fallback";
static const char kFontWenQuanYiMicroHei[] = "WenQuanYi Micro Hei";
static const char kFontNanumGothic[] = "NanumGothic";
void
gfxPlatformHeadless::GetCommonFallbackFonts(uint32_t aCh, uint32_t aNextCh,
Script aRunScript,
nsTArray<const char*>& aFontList)
{
EmojiPresentation emoji = GetEmojiPresentation(aCh);
EmojiPresentation eNext = GetEmojiPresentation(aNextCh, true);
if (aNextCh != kVariationSelector15 &&
emoji != EmojiPresentation::TextOnly &&
(emoji != EmojiPresentation::TextDefault ||
eNext == EmojiPresentation::EmojiComponent)) {
aFontList.AppendElement(kFontTwemojiMozilla);
}
aFontList.AppendElement(kFontDejaVuSerif);
aFontList.AppendElement(kFontFreeSerif);
aFontList.AppendElement(kFontDejaVuSans);
aFontList.AppendElement(kFontFreeSans);
// add fonts for CJK ranges
// xxx - this isn't really correct, should use the same CJK font ordering
// as the pref font code
if (aCh >= 0x3000 &&
((aCh < 0xe000) ||
(aCh >= 0xf900 && aCh < 0xfff0) ||
((aCh >> 16) == 2))) {
aFontList.AppendElement(kFontTakaoPGothic);
aFontList.AppendElement(kFontDroidSansFallback);
aFontList.AppendElement(kFontWenQuanYiMicroHei);
aFontList.AppendElement(kFontNanumGothic);
}
}
gfxPlatformFontList*
gfxPlatformHeadless::CreatePlatformFontList()
{
gfxPlatformFontList* list = new gfxFcPlatformFontList();
if (NS_SUCCEEDED(list->InitFontList())) {
return list;
}
gfxPlatformFontList::Shutdown();
return nullptr;
}
nsresult
gfxPlatformHeadless::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName)
{
gfxPlatformFontList::PlatformFontList()->
GetStandardFamilyName(aFontName, aFamilyName);
return NS_OK;
}
gfxFontGroup *
gfxPlatformHeadless::CreateFontGroup(const FontFamilyList& aFontFamilyList,
const gfxFontStyle* aStyle,
gfxTextPerfMetrics* aTextPerf,
gfxUserFontSet* aUserFontSet,
gfxFloat aDevToCssSize)
{
return new gfxFontGroup(aFontFamilyList, aStyle, aTextPerf,
aUserFontSet, aDevToCssSize);
}
gfxFontEntry*
gfxPlatformHeadless::LookupLocalFont(const nsAString& aFontName,
uint16_t aWeight,
int16_t aStretch,
uint8_t aStyle)
{
gfxPlatformFontList* pfl = gfxPlatformFontList::PlatformFontList();
return pfl->LookupLocalFont(aFontName, aWeight, aStretch,
aStyle);
}
gfxFontEntry*
gfxPlatformHeadless::MakePlatformFont(const nsAString& aFontName,
uint16_t aWeight,
int16_t aStretch,
uint8_t aStyle,
const uint8_t* aFontData,
uint32_t aLength)
{
gfxPlatformFontList* pfl = gfxPlatformFontList::PlatformFontList();
return pfl->MakePlatformFont(aFontName, aWeight, aStretch,
aStyle, aFontData, aLength);
}
bool
gfxPlatformHeadless::IsFontFormatSupported(nsIURI *aFontURI, uint32_t aFormatFlags)
{
// check for strange format flags
NS_ASSERTION(!(aFormatFlags & gfxUserFontSet::FLAG_FORMAT_NOT_USED),
"strange font format hint set");
// accept supported formats
// Pango doesn't apply features from AAT TrueType extensions.
// Assume that if this is the only SFNT format specified,
// then AAT extensions are required for complex script support.
if (aFormatFlags & gfxUserFontSet::FLAG_FORMATS_COMMON) {
return true;
}
// reject all other formats, known and unknown
if (aFormatFlags != 0) {
return false;
}
// no format hint set, need to look at data
return true;
}
static int32_t sDPI = 0;
int32_t
gfxPlatformHeadless::GetDPI()
{
if (!sDPI) {
// Make sure init is run so we have a resolution
sDPI = 96;
if (sDPI <= 0) {
// Fall back to something sane
sDPI = 96;
}
}
return sDPI;
}
double
gfxPlatformHeadless::GetDPIScale()
{
// Integer scale factors work well with GTK window scaling, image scaling,
// and pixel alignment, but there is a range where 1 is too small and 2 is
// too big. An additional step of 1.5 is added because this is common
// scale on WINNT and at this ratio the advantages of larger rendering
// outweigh the disadvantages from scaling and pixel mis-alignment.
int32_t dpi = GetDPI();
if (dpi < 144) {
return 1.0;
} else if (dpi < 168) {
return 1.5;
} else {
return round(dpi/96.0);
}
}
bool
gfxPlatformHeadless::UseImageOffscreenSurfaces()
{
return GetDefaultContentBackend() != mozilla::gfx::BackendType::CAIRO ||
gfxPrefs::UseImageOffscreenSurfaces();
}
gfxImageFormat
gfxPlatformHeadless::GetOffscreenFormat()
{
// Make sure there is a screen
return SurfaceFormat::X8R8G8B8_UINT32;
}
void gfxPlatformHeadless::FontsPrefsChanged(const char *aPref)
{
// only checking for generic substitions, pass other changes up
if (strcmp(GFX_PREF_MAX_GENERIC_SUBSTITUTIONS, aPref)) {
gfxPlatform::FontsPrefsChanged(aPref);
return;
}
mMaxGenericSubstitutions = UNINITIALIZED_VALUE;
gfxFcPlatformFontList* pfl = gfxFcPlatformFontList::PlatformFontList();
pfl->ClearGenericMappings();
FlushFontAndWordCaches();
}
uint32_t gfxPlatformHeadless::MaxGenericSubstitions()
{
if (mMaxGenericSubstitutions == UNINITIALIZED_VALUE) {
mMaxGenericSubstitutions =
Preferences::GetInt(GFX_PREF_MAX_GENERIC_SUBSTITUTIONS, 3);
if (mMaxGenericSubstitutions < 0) {
mMaxGenericSubstitutions = 3;
}
}
return uint32_t(mMaxGenericSubstitutions);
}
void
gfxPlatformHeadless::GetPlatformCMSOutputProfile(void *&mem, size_t &size)
{
mem = nullptr;
size = 0;
#ifdef MOZ_X11
GdkDisplay *display = gdk_display_get_default();
if (!GDK_IS_X11_DISPLAY(display))
return;
const char EDID1_ATOM_NAME[] = "XFree86_DDC_EDID1_RAWDATA";
const char ICC_PROFILE_ATOM_NAME[] = "_ICC_PROFILE";
Atom edidAtom, iccAtom;
Display *dpy = GDK_DISPLAY_XDISPLAY(display);
// In xpcshell tests, we never initialize X and hence don't have a Display.
// In this case, there's no output colour management to be done, so we just
// return with nullptr.
if (!dpy)
return;
Window root = gdk_x11_get_default_root_xwindow();
Atom retAtom;
int retFormat;
unsigned long retLength, retAfter;
unsigned char *retProperty ;
iccAtom = XInternAtom(dpy, ICC_PROFILE_ATOM_NAME, TRUE);
if (iccAtom) {
// read once to get size, once for the data
if (Success == XGetWindowProperty(dpy, root, iccAtom,
0, INT_MAX /* length */,
False, AnyPropertyType,
&retAtom, &retFormat, &retLength,
&retAfter, &retProperty)) {
if (retLength > 0) {
void *buffer = malloc(retLength);
if (buffer) {
memcpy(buffer, retProperty, retLength);
mem = buffer;
size = retLength;
}
}
XFree(retProperty);
if (size > 0) {
#ifdef DEBUG_tor
fprintf(stderr,
"ICM profile read from %s successfully\n",
ICC_PROFILE_ATOM_NAME);
#endif
return;
}
}
}
edidAtom = XInternAtom(dpy, EDID1_ATOM_NAME, TRUE);
if (edidAtom) {
if (Success == XGetWindowProperty(dpy, root, edidAtom, 0, 32,
False, AnyPropertyType,
&retAtom, &retFormat, &retLength,
&retAfter, &retProperty)) {
double gamma;
qcms_CIE_xyY whitePoint;
qcms_CIE_xyYTRIPLE primaries;
if (retLength != 128) {
#ifdef DEBUG_tor
fprintf(stderr, "Short EDID data\n");
#endif
return;
}
// Format documented in "VESA E-EDID Implementation Guide"
gamma = (100 + retProperty[0x17]) / 100.0;
whitePoint.x = ((retProperty[0x21] << 2) |
(retProperty[0x1a] >> 2 & 3)) / 1024.0;
whitePoint.y = ((retProperty[0x22] << 2) |
(retProperty[0x1a] >> 0 & 3)) / 1024.0;
whitePoint.Y = 1.0;
primaries.red.x = ((retProperty[0x1b] << 2) |
(retProperty[0x19] >> 6 & 3)) / 1024.0;
primaries.red.y = ((retProperty[0x1c] << 2) |
(retProperty[0x19] >> 4 & 3)) / 1024.0;
primaries.red.Y = 1.0;
primaries.green.x = ((retProperty[0x1d] << 2) |
(retProperty[0x19] >> 2 & 3)) / 1024.0;
primaries.green.y = ((retProperty[0x1e] << 2) |
(retProperty[0x19] >> 0 & 3)) / 1024.0;
primaries.green.Y = 1.0;
primaries.blue.x = ((retProperty[0x1f] << 2) |
(retProperty[0x1a] >> 6 & 3)) / 1024.0;
primaries.blue.y = ((retProperty[0x20] << 2) |
(retProperty[0x1a] >> 4 & 3)) / 1024.0;
primaries.blue.Y = 1.0;
XFree(retProperty);
#ifdef DEBUG_tor
fprintf(stderr, "EDID gamma: %f\n", gamma);
fprintf(stderr, "EDID whitepoint: %f %f %f\n",
whitePoint.x, whitePoint.y, whitePoint.Y);
fprintf(stderr, "EDID primaries: [%f %f %f] [%f %f %f] [%f %f %f]\n",
primaries.Red.x, primaries.Red.y, primaries.Red.Y,
primaries.Green.x, primaries.Green.y, primaries.Green.Y,
primaries.Blue.x, primaries.Blue.y, primaries.Blue.Y);
#endif
qcms_data_create_rgb_with_gamma(whitePoint, primaries, gamma, &mem, &size);
#ifdef DEBUG_tor
if (size > 0) {
fprintf(stderr,
"ICM profile read from %s successfully\n",
EDID1_ATOM_NAME);
}
#endif
}
}
#endif
}
#if (MOZ_WIDGET_GTK == 2)
void
gfxPlatformHeadless::SetGdkDrawable(cairo_surface_t *target,
GdkDrawable *drawable)
{
if (cairo_surface_status(target))
return;
g_object_ref(drawable);
cairo_surface_set_user_data (target,
&cairo_gdk_drawable_key,
drawable,
g_object_unref);
}
GdkDrawable *
gfxPlatformHeadless::GetGdkDrawable(cairo_surface_t *target)
{
if (cairo_surface_status(target))
return nullptr;
GdkDrawable *result;
result = (GdkDrawable*) cairo_surface_get_user_data (target,
&cairo_gdk_drawable_key);
if (result)
return result;
#ifdef MOZ_X11
if (cairo_surface_get_type(target) != CAIRO_SURFACE_TYPE_XLIB)
return nullptr;
// try looking it up in gdk's table
result = (GdkDrawable*) gdk_xid_table_lookup(cairo_xlib_surface_get_drawable(target));
if (result) {
SetGdkDrawable(target, result);
return result;
}
#endif
return nullptr;
}
#endif
#ifdef GL_PROVIDER_GLX
class GLXVsyncSource final : public VsyncSource
{
public:
GLXVsyncSource()
{
MOZ_ASSERT(NS_IsMainThread());
mGlobalDisplay = new GLXDisplay();
}
virtual ~GLXVsyncSource()
{
MOZ_ASSERT(NS_IsMainThread());
}
virtual Display& GetGlobalDisplay() override
{
return *mGlobalDisplay;
}
class GLXDisplay final : public VsyncSource::Display
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GLXDisplay)
public:
GLXDisplay() : mGLContext(nullptr)
, mXDisplay(nullptr)
, mSetupLock("GLXVsyncSetupLock")
, mVsyncThread("GLXVsyncThread")
, mVsyncTask(nullptr)
, mVsyncEnabledLock("GLXVsyncEnabledLock")
, mVsyncEnabled(false)
{
}
// Sets up the display's GL context on a worker thread.
// Required as GLContexts may only be used by the creating thread.
// Returns true if setup was a success.
bool Setup()
{
MonitorAutoLock lock(mSetupLock);
MOZ_ASSERT(NS_IsMainThread());
if (!mVsyncThread.Start())
return false;
RefPtr<Runnable> vsyncSetup = NewRunnableMethod(this, &GLXDisplay::SetupGLContext);
mVsyncThread.message_loop()->PostTask(vsyncSetup.forget());
// Wait until the setup has completed.
lock.Wait();
return mGLContext != nullptr;
}
// Called on the Vsync thread to setup the GL context.
void SetupGLContext()
{
MonitorAutoLock lock(mSetupLock);
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!mGLContext, "GLContext already setup!");
// Create video sync timer on a separate Display to prevent locking the
// main thread X display.
mXDisplay = XOpenDisplay(nullptr);
if (!mXDisplay) {
lock.NotifyAll();
return;
}
// Most compositors wait for vsync events on the root window.
Window root = DefaultRootWindow(mXDisplay);
int screen = DefaultScreen(mXDisplay);
ScopedXFree<GLXFBConfig> cfgs;
GLXFBConfig config;
int visid;
if (!gl::GLContextGLX::FindFBConfigForWindow(mXDisplay, screen, root,
&cfgs, &config, &visid)) {
lock.NotifyAll();
return;
}
mGLContext = gl::GLContextGLX::CreateGLContext(
gl::CreateContextFlags::NONE,
gl::SurfaceCaps::Any(),
nullptr,
false,
mXDisplay,
root,
config);
if (!mGLContext) {
lock.NotifyAll();
return;
}
mGLContext->MakeCurrent();
// Test that SGI_video_sync lets us get the counter.
unsigned int syncCounter = 0;
if (gl::sGLXLibrary.xGetVideoSync(&syncCounter) != 0) {
mGLContext = nullptr;
}
lock.NotifyAll();
}
virtual void EnableVsync() override
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mGLContext, "GLContext not setup!");
MonitorAutoLock lock(mVsyncEnabledLock);
if (mVsyncEnabled) {
return;
}
mVsyncEnabled = true;
// If the task has not nulled itself out, it hasn't yet realized
// that vsync was disabled earlier, so continue its execution.
if (!mVsyncTask) {
mVsyncTask = NewRunnableMethod(this, &GLXDisplay::RunVsync);
RefPtr<Runnable> addrefedTask = mVsyncTask;
mVsyncThread.message_loop()->PostTask(addrefedTask.forget());
}
}
virtual void DisableVsync() override
{
MonitorAutoLock lock(mVsyncEnabledLock);
mVsyncEnabled = false;
}
virtual bool IsVsyncEnabled() override
{
MonitorAutoLock lock(mVsyncEnabledLock);
return mVsyncEnabled;
}
virtual void Shutdown() override
{
MOZ_ASSERT(NS_IsMainThread());
DisableVsync();
// Cleanup thread-specific resources before shutting down.
RefPtr<Runnable> shutdownTask = NewRunnableMethod(this, &GLXDisplay::Cleanup);
mVsyncThread.message_loop()->PostTask(shutdownTask.forget());
// Stop, waiting for the cleanup task to finish execution.
mVsyncThread.Stop();
}
private:
virtual ~GLXDisplay()
{
}
void RunVsync()
{
MOZ_ASSERT(!NS_IsMainThread());
mGLContext->MakeCurrent();
unsigned int syncCounter = 0;
gl::sGLXLibrary.xGetVideoSync(&syncCounter);
for (;;) {
{
MonitorAutoLock lock(mVsyncEnabledLock);
if (!mVsyncEnabled) {
mVsyncTask = nullptr;
return;
}
}
TimeStamp lastVsync = TimeStamp::Now();
bool useSoftware = false;
// Wait until the video sync counter reaches the next value by waiting
// until the parity of the counter value changes.
unsigned int nextSync = syncCounter + 1;
int status;
if ((status = gl::sGLXLibrary.xWaitVideoSync(2, nextSync % 2, &syncCounter)) != 0) {
gfxWarningOnce() << "glXWaitVideoSync returned " << status;
useSoftware = true;
}
if (syncCounter == (nextSync - 1)) {
gfxWarningOnce() << "glXWaitVideoSync failed to increment the sync counter.";
useSoftware = true;
}
if (useSoftware) {
double remaining = (1000.f / 60.f) -
(TimeStamp::Now() - lastVsync).ToMilliseconds();
if (remaining > 0) {
PlatformThread::Sleep(remaining);
}
}
lastVsync = TimeStamp::Now();
NotifyVsync(lastVsync);
}
}
void Cleanup() {
MOZ_ASSERT(!NS_IsMainThread());
mGLContext = nullptr;
XCloseDisplay(mXDisplay);
}
// Owned by the vsync thread.
RefPtr<gl::GLContextGLX> mGLContext;
_XDisplay* mXDisplay;
Monitor mSetupLock;
base::Thread mVsyncThread;
RefPtr<Runnable> mVsyncTask;
Monitor mVsyncEnabledLock;
bool mVsyncEnabled;
};
private:
// We need a refcounted VsyncSource::Display to use chromium IPC runnables.
RefPtr<GLXDisplay> mGlobalDisplay;
};
already_AddRefed<gfx::VsyncSource>
gfxPlatformHeadless::CreateHardwareVsyncSource()
{
// Only use GLX vsync when the OpenGL compositor is being used.
// The extra cost of initializing a GLX context while blocking the main
// thread is not worth it when using basic composition.
if (gfxConfig::IsEnabled(Feature::HW_COMPOSITING)) {
if (gl::sGLXLibrary.SupportsVideoSync()) {
RefPtr<VsyncSource> vsyncSource = new GLXVsyncSource();
VsyncSource::Display& display = vsyncSource->GetGlobalDisplay();
if (!static_cast<GLXVsyncSource::GLXDisplay&>(display).Setup()) {
NS_WARNING("Failed to setup GLContext, falling back to software vsync.");
return gfxPlatform::CreateHardwareVsyncSource();
}
return vsyncSource.forget();
}
NS_WARNING("SGI_video_sync unsupported. Falling back to software vsync.");
}
return gfxPlatform::CreateHardwareVsyncSource();
}
#endif
// Not GLX-specific: must be defined regardless of GL_PROVIDER_GLX so the
// vtable slot resolves in a headless (no X/GLX) build.
bool
gfxPlatformHeadless::SupportsApzTouchInput() const
{
int value = gfxPrefs::TouchEventsEnabled();
return value == 1 || value == 2;
}
+150
View File
@@ -0,0 +1,150 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GFX_PLATFORM_GTK_H
#define GFX_PLATFORM_GTK_H
#include "gfxPlatform.h"
#include "nsAutoRef.h"
#include "nsTArray.h"
#include "mozilla/gfx/gfxVars.h"
#if (MOZ_WIDGET_GTK == 2)
extern "C" {
typedef struct _GdkDrawable GdkDrawable;
}
#endif
#ifdef MOZ_X11
struct _XDisplay;
typedef struct _XDisplay Display;
#endif // MOZ_X11
class gfxPlatformHeadless : public gfxPlatform {
public:
gfxPlatformHeadless();
virtual ~gfxPlatformHeadless();
static gfxPlatformHeadless *GetPlatform() {
return (gfxPlatformHeadless*) gfxPlatform::GetPlatform();
}
virtual already_AddRefed<gfxASurface>
CreateOffscreenSurface(const IntSize& aSize,
gfxImageFormat aFormat) override;
virtual nsresult GetFontList(nsIAtom *aLangGroup,
const nsACString& aGenericFamily,
nsTArray<nsString>& aListOfFonts) override;
virtual nsresult UpdateFontList() override;
virtual void
GetCommonFallbackFonts(uint32_t aCh, uint32_t aNextCh,
Script aRunScript,
nsTArray<const char*>& aFontList) override;
virtual gfxPlatformFontList* CreatePlatformFontList() override;
virtual nsresult GetStandardFamilyName(const nsAString& aFontName,
nsAString& aFamilyName) override;
gfxFontGroup*
CreateFontGroup(const mozilla::FontFamilyList& aFontFamilyList,
const gfxFontStyle *aStyle,
gfxTextPerfMetrics* aTextPerf,
gfxUserFontSet *aUserFontSet,
gfxFloat aDevToCssSize) override;
/**
* Look up a local platform font using the full font face name (needed to
* support @font-face src local() )
*/
virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName,
uint16_t aWeight,
int16_t aStretch,
uint8_t aStyle) override;
/**
* Activate a platform font (needed to support @font-face src url() )
*
*/
virtual gfxFontEntry* MakePlatformFont(const nsAString& aFontName,
uint16_t aWeight,
int16_t aStretch,
uint8_t aStyle,
const uint8_t* aFontData,
uint32_t aLength) override;
/**
* Check whether format is supported on a platform or not (if unclear,
* returns true).
*/
virtual bool IsFontFormatSupported(nsIURI *aFontURI,
uint32_t aFormatFlags) override;
/**
* Calls XFlush if xrender is enabled.
*/
virtual void FlushContentDrawing() override;
#if (MOZ_WIDGET_GTK == 2)
static void SetGdkDrawable(cairo_surface_t *target,
GdkDrawable *drawable);
static GdkDrawable *GetGdkDrawable(cairo_surface_t *target);
#endif
static int32_t GetDPI();
static double GetDPIScale();
#ifdef MOZ_X11
virtual void GetAzureBackendInfo(mozilla::widget::InfoObject &aObj) override {
gfxPlatform::GetAzureBackendInfo(aObj);
aObj.DefineProperty("CairoUseXRender", mozilla::gfx::gfxVars::UseXRender());
}
#endif
bool UseImageOffscreenSurfaces();
virtual gfxImageFormat GetOffscreenFormat() override;
bool SupportsApzWheelInput() const override {
return true;
}
bool SupportsApzTouchInput() const override;
void FontsPrefsChanged(const char *aPref) override;
// maximum number of fonts to substitute for a generic
uint32_t MaxGenericSubstitions();
bool SupportsPluginDirectBitmapDrawing() override {
return true;
}
#ifdef GL_PROVIDER_GLX
already_AddRefed<mozilla::gfx::VsyncSource> CreateHardwareVsyncSource() override;
#endif
#ifdef MOZ_X11
Display* GetCompositorDisplay() {
return mCompositorDisplay;
}
#endif // MOZ_X11
protected:
int8_t mMaxGenericSubstitutions;
private:
virtual void GetPlatformCMSOutputProfile(void *&mem,
size_t &size) override;
#ifdef MOZ_X11
Display* mCompositorDisplay;
#endif
};
#endif /* GFX_PLATFORM_GTK_H */
+16
View File
@@ -74,6 +74,22 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
'gfxQuartzSurface.cpp',
'PrintTargetCG.cpp',
]
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'headless':
# Jihad headless (no X/GTK): fontconfig/freetype fonts + a memory gfxPlatform.
EXPORTS += [
'gfxFT2FontBase.h',
'gfxPlatformHeadless.h',
]
EXPORTS.mozilla.gfx += [
'PrintTargetPDF.h',
]
SOURCES += [
'gfxFcPlatformFontList.cpp',
'gfxFT2FontBase.cpp',
'gfxFT2Utils.cpp',
'gfxPlatformHeadless.cpp',
'PrintTargetPDF.cpp',
]
elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
EXPORTS += [
'gfxFT2FontBase.h',
+8
View File
@@ -6,6 +6,14 @@
GeckoProgram(CONFIG['MOZ_CHILD_PROCESS_NAME'], linkage='dependent')
SOURCES += [
# JihadPmLogSem.c interposes sem_open/sem_close for the ONE name "PmLogLib". The device's
# Flash pulls in libPmLogLib.so, whose constructor sem_wait()s a named semaphore created
# by webOS's glibc 2.8; glibc 2.21 changed sem_t's value word to (tokens << 1), so our
# bundled 2.23 reads that semaphore as "no tokens, waiters pending" and the dlopen never
# returns. It has to be in THIS directory: a dlopened plugin resolves its PLT against the
# global scope, which the program image heads, and ipc/app is where the program is linked
# (ipc/contentproc only produces an archive this link does not use).
'../contentproc/JihadPmLogSem.c',
'MozillaRuntimeMain.cpp',
]
+6
View File
@@ -146,7 +146,13 @@ MessageLoop::MessageLoop(Type type, nsIThread* aThread)
#if defined(OS_MACOSX)
pump_ = base::MessagePumpMac::Create();
#elif defined(OS_LINUX) || defined(OS_BSD) || defined(OS_SOLARIS)
#if defined(MOZ_WIDGET_GTK)
pump_ = new base::MessagePumpForUI();
#else
// Jihad headless: no GTK UI pump; the embedder drives events via
// NS_ProcessNextEvent, so a default (non-UI) message pump suffices.
pump_ = new base::MessagePumpDefault();
#endif
#endif // OS_LINUX
} else if (type_ == TYPE_IO) {
pump_ = new base::MessagePumpLibevent();
+135
View File
@@ -0,0 +1,135 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* Jihad Browser — the /PmLogLib named-semaphore ABI trap.
*
* Compiled into every one of our binaries that can dlopen a device NPAPI plugin: the
* daemon (its plugin scan) and plugin-container (the plugin itself). Plain C, no headers
* from UXP or from the daemon, so the same file drops into both build systems unchanged.
*/
// ── WHAT THIS IS FOR ────────────────────────────────────────────────────────────────────
//
// The device's libflashplayer.so has libWebKitLuna.so as a DT_NEEDED, which drags in
// libPmLogLib.so. PmLogLib's ELF constructor opens the POSIX named semaphore "PmLogLib"
// and sem_wait()s it to guard a SysV shared-memory table of log contexts that every
// process on the device shares.
//
// glibc changed sem_t's layout in 2.21. The value word went from a raw token count to
// (tokens << 1) | has-waiters. webOS 3's userland is glibc 2.8 — the OLD layout — and
// everything we cross-build runs on the bundled glibc 2.23, the NEW one. /dev/shm/
// sem.PmLogLib is created once per boot by whichever process opens it first, in that
// process's layout, and then outlives every user of it.
//
// When a system process wins that race the word holds a raw 1, meaning "one token". Our
// 2.23 sem_wait reads the same word as ZERO tokens with the waiters bit set, so it goes
// straight to futex_wait and never returns. dlopen never completes and whoever called it
// wedges: measured on device 2026-08-10 as
// futex(0x2dd98000, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 1, NULL, ffffffff
// immediately after the mmap of /dev/shm/sem.PmLogLib, with every library already loaded.
//
// That is why this reads as an intermittent, reboot-triggered failure on binaries nobody
// touched: it is decided by a boot race, not by our code. The same dlopen run under the
// device's own /lib/ld-linux.so.3 completes and returns both Flash MIME types.
//
// ── WHY INTERPOSE RATHER THAN REPAIR THE SEMAPHORE ──────────────────────────────────────
//
// Rewriting /dev/shm/sem.PmLogLib into our layout, or posting it once to make it readable
// to us, both work — and both hand every OTHER process on the device an extra token on a
// lock guarding a shared table. That silently weakens PmLogLib's mutual exclusion
// system-wide to fix a browser. Interposing ONE name does not: PmLogLib gets a semaphore
// that never leaves this process, so no other glibc ever parses its layout, and the file
// in /dev/shm is not touched at all.
//
// Everything else is forwarded to the real implementation untouched, which MATTERS: our
// own shared frame buffers are named semaphores too (/dev/shm/sem.browserserver.<pid>-<n>,
// created here and opened by the adapter inside LunaSysMgr), and those genuinely must stay
// shared across the process boundary.
#define _GNU_SOURCE
#include <dlfcn.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdarg.h>
#include <stddef.h>
#include <string.h>
// PmLogLib asks for the name WITHOUT a leading slash (verified on device: the interposer
// logged sem_open("PmLogLib")). POSIX says a portable name starts with '/', and glibc
// accepts both, so match both rather than trusting either spelling.
// Link anchor. plugin-container builds this TU into a static archive, and an archive member
// is only pulled in to satisfy an UNDEFINED symbol — sem_open is already defined by
// libpthread, so nothing was undefined and the whole file was silently dropped from the
// link. Calling this from the program's entry point forces the member in. The daemon links
// the object directly and does not need it; it costs one call there.
__attribute__((visibility("default")))
int jihad_pmlog_sem_installed(void) { return 1; }
static int jihad_is_pmlog_name(const char* name)
{
if (!name) return 0;
if (name[0] == '/') ++name;
return strcmp(name, "PmLogLib") == 0;
}
static sem_t g_pmlogSem;
static pthread_once_t g_pmlogSemOnce = PTHREAD_ONCE_INIT;
static unsigned int g_pmlogSemInitial = 1;
static void jihad_pmlog_sem_init(void)
{
// pshared = 0. Process-private is the whole point: it can never be observed, and so can
// never be misread, by a glibc with a different sem_t layout.
sem_init(&g_pmlogSem, 0, g_pmlogSemInitial);
}
__attribute__((visibility("default")))
sem_t* sem_open(const char* name, int oflag, ...)
{
static sem_t* (*real_sem_open)(const char*, int, ...);
if (!real_sem_open)
real_sem_open = (sem_t* (*)(const char*, int, ...))dlsym(RTLD_NEXT, "sem_open");
// The mode/value pair is only present when O_CREAT is set; reading it otherwise walks off
// the end of the argument list.
mode_t mode = 0;
unsigned int value = 0;
const int creating = (oflag & O_CREAT) != 0;
if (creating) {
va_list ap;
va_start(ap, oflag);
mode = (mode_t)va_arg(ap, unsigned int);
value = va_arg(ap, unsigned int);
va_end(ap);
}
if (jihad_is_pmlog_name(name)) {
if (creating) g_pmlogSemInitial = value;
pthread_once(&g_pmlogSemOnce, jihad_pmlog_sem_init);
return &g_pmlogSem;
}
if (!real_sem_open) return SEM_FAILED;
if (creating) return real_sem_open(name, oflag, mode, value);
return real_sem_open(name, oflag);
}
// PmLogLib closes the semaphore on unload. glibc's sem_close looks the pointer up in its
// table of NAMED semaphores, would not find ours, and would return EINVAL — harmless today,
// but only by luck. Answer for our own pointer and forward everything else.
__attribute__((visibility("default")))
int sem_close(sem_t* sem)
{
static int (*real_sem_close)(sem_t*);
if (!real_sem_close)
real_sem_close = (int (*)(sem_t*))dlsym(RTLD_NEXT, "sem_close");
// Deliberately NOT sem_destroy: the plugin can be unloaded and reloaded within one
// process (the scan does exactly that), and a destroyed static would be reused.
if (sem == &g_pmlogSem) return 0;
if (!real_sem_close) return 0;
return real_sem_close(sem);
}
+4
View File
@@ -9,6 +9,10 @@ SOURCES += [
'plugin-container.cpp',
]
# JihadPmLogSem.c lives here next to its only caller but is compiled by ipc/app, which is
# where the plugin-container PROGRAM is linked; this directory only produces an archive that
# that link does not use. See ipc/app/moz.build.
include('/ipc/chromium/chromium-config.mozbuild')
if CONFIG['OS_ARCH'] == 'WINNT':
+117
View File
@@ -3,10 +3,16 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdlib.h> // getenv / unsetenv (JIHAD: see main)
#include "nsXPCOM.h"
#include "nsXULAppAPI.h"
#include "nsAutoPtr.h"
// JihadPmLogSem.c — C, and deliberately carries no header, so it drops unchanged into both
// this build and the daemon's. Declared here rather than in one because that is the entire
// interface: one call whose only job is to keep the archive member in the link.
extern "C" int jihad_pmlog_sem_installed(void);
#ifdef XP_WIN
#include <windows.h>
// we want a wmain entry point
@@ -19,6 +25,82 @@
#include <unistd.h>
#endif
// JIHAD DIAGNOSTIC (R7): the child process dies with SIGSEGV between a successful
// InitForChrome and handling its first IPC message, and the device's own minicore reporter
// is out of report slots ("no room for new reports"), so nothing records where. This prints
// the faulting address, a backtrace, and /proc/self/maps to stderr — which the child
// inherits from the daemon, so it lands in the variant's daemon.log. The maps dump is the
// part that matters on ARM: even a single frame is enough to name the faulting library.
#if defined(OS_POSIX) || defined(XP_UNIX)
#include <execinfo.h>
#include <signal.h>
#include <ucontext.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
static void
jihad_child_fault_handler(int sig, siginfo_t* info, void* ctx)
{
void* frames[32];
int n = backtrace(frames, 32);
fprintf(stderr, "[jihad-npapi-child] FAULT sig=%d addr=%p pid=%d frames=%d\n",
sig, info ? info->si_addr : nullptr, (int)getpid(), n);
// backtrace() returns nothing useful from a signal frame on ARM (no unwind tables
// through the trampoline), so take the registers straight out of the signal context.
// pc and lr against the maps below give the faulting library and offset, and
// addr2line on the unstripped build turns that into file:line.
#if defined(__arm__)
if (ctx) {
ucontext_t* uc = (ucontext_t*)ctx;
fprintf(stderr, "[jihad-npapi-child] FAULT pc=%08lx lr=%08lx sp=%08lx r0=%08lx\n",
(unsigned long)uc->uc_mcontext.arm_pc,
(unsigned long)uc->uc_mcontext.arm_lr,
(unsigned long)uc->uc_mcontext.arm_sp,
(unsigned long)uc->uc_mcontext.arm_r0);
}
#else
(void)ctx;
#endif
fflush(stderr);
backtrace_symbols_fd(frames, n, STDERR_FILENO);
FILE* maps = fopen("/proc/self/maps", "r");
if (maps) {
char line[512];
fputs("[jihad-npapi-child] --- maps ---\n", stderr);
while (fgets(line, sizeof(line), maps)) {
// Only the executable mappings; the full map is hundreds of lines of noise.
if (strstr(line, "r-xp")) {
fputs("[jihad-npapi-child] ", stderr);
fputs(line, stderr);
}
}
fclose(maps);
}
fflush(stderr);
// Restore the default disposition and re-raise so the exit status still says "crashed".
signal(sig, SIG_DFL);
raise(sig);
}
static void
jihad_install_child_fault_handler()
{
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = jihad_child_fault_handler;
sa.sa_flags = SA_SIGINFO;
sigemptyset(&sa.sa_mask);
sigaction(SIGSEGV, &sa, nullptr);
sigaction(SIGBUS, &sa, nullptr);
sigaction(SIGILL, &sa, nullptr);
sigaction(SIGFPE, &sa, nullptr);
}
#endif
#ifdef MOZ_GMP
#include "GMPLoader.h"
@@ -38,6 +120,41 @@ content_process_main(int argc, char* argv[])
return 3;
}
#if defined(OS_POSIX) || defined(XP_UNIX)
jihad_install_child_fault_handler();
#endif
// JIHAD (R7): force JihadPmLogSem.o into the link and say so. It interposes sem_open for
// the single name "PmLogLib", without which dlopening the device's Flash deadlocks this
// process forever — libPmLogLib's constructor waits on a named semaphore created by
// webOS's glibc 2.8, whose sem_t value word our glibc 2.23 reads as "no tokens, waiters
// pending". The call is also the only cheap proof the interposer survived the link: it
// lives in a static archive, and an archive member with no undefined symbol to satisfy
// is silently dropped. See render/goanna/JihadPmLogSem.c.
fprintf(stderr, "[jihad-npapi-child] pmlog sem interposition=%d\n",
jihad_pmlog_sem_installed());
// JIHAD DIAGNOSTIC (R7): the child's own view of its argv. Doubles as the control that
// child stderr reaches the parent's log at all — every other child probe is worthless
// until this line is seen.
fprintf(stderr, "[jihad-npapi-child] main argc=%d\n", argc);
for (int i = 0; i < argc; i++) {
fprintf(stderr, "[jihad-npapi-child] argv[%d]=%s\n", i, argv[i]);
}
fflush(stderr);
// JIHAD (2026-10-05): DO NOT HAND OUR LIBRARY PATH TO WHAT THE PLUGIN RUNS.
// This process is started through the bundled loader with an explicit --library-path,
// which is what its own later dlopen()s search; the LD_LIBRARY_PATH it also inherits
// is not needed by it. But it is inherited again by anything the plugin spawns, and
// Flash for Linux runs `sh -c "ps x | grep netscape"` at start-up: the device's own
// /bin/sh (built for its glibc 2.8) then loads the bundled glibc 2.23 and dies with
// SIGSEGV, leaving a crash report in /var/log/reports for every page with Flash on it.
// Only when the bundled loader is in use; a desktop build keeps its environment.
if (getenv("MOZ_CHILD_PROCESS_LOADER")) {
unsetenv("LD_LIBRARY_PATH");
}
#ifdef MOZ_GMP
XREChildData childData;
#endif
+28
View File
@@ -160,6 +160,13 @@ GeckoChildProcessHost::GetPathToBinary(FilePath& exePath, GeckoProcessType proce
exePath = exePath.AppendASCII(MOZ_CHILD_PROCESS_NAME);
// JIHAD DIAGNOSTIC (R7): the resolved child path, and which branch produced it. In this
// embedding the daemon is exec'd as `./ld-2.23.so … ./jihad-browserserver`, so argv[0] is the
// LOADER — if the directory-service branch is not taken, the fallback dirname(argv[0]) is
// relative to that, not to the daemon.
fprintf(stderr, "[jihad-npapi] child binary path=%s (dirService=%d)\n",
exePath.value().c_str(), (int)ShouldHaveDirectoryService());
return BinaryPathType::PluginContainer;
}
@@ -662,6 +669,27 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
std::vector<std::string> childArgv;
// Optional ELF loader prefix for the child process.
//
// An embedder whose bundled glibc differs from the host system's cannot exec the child
// binary directly: its PT_INTERP names the SYSTEM loader, which then resolves the child's
// libraries against the bundled set and dies before main(). Exporting these two variables
// makes the child be launched exactly the way such an embedder launches itself —
// <loader> --library-path <path> <child> <args…>
// — which runs the child in the same process image (no extra fork, no shell hop, so the
// pid we hand to waitpid and the inherited IPC channel fd are unaffected).
//
// Both unset is upstream behaviour, unchanged.
const char* childLoader = PR_GetEnv("MOZ_CHILD_PROCESS_LOADER");
if (childLoader && *childLoader) {
childArgv.push_back(childLoader);
const char* loaderLibPath = PR_GetEnv("MOZ_CHILD_PROCESS_LOADER_PATH");
if (loaderLibPath && *loaderLibPath) {
childArgv.push_back("--library-path");
childArgv.push_back(loaderLibPath);
}
}
childArgv.push_back(exePath.value());
if (pathType == BinaryPathType::Self) {
@@ -1,4 +1,3 @@
// |jit-test| --ion-sink=on
// Sink Algorithm should not move instruction into merge blocks
// which have no corresponding pc.
+1 -1
View File
@@ -2439,7 +2439,7 @@ static const VMFunction GetOrCreateModuleMetaObjectInfo =
void
CodeGenerator::visitModuleMetadata(LModuleMetadata* lir)
{
pushArg(ImmPtr(lir->mir()->module()));
pushArg(ImmGCPtr(lir->mir()->module()));
callVM(GetOrCreateModuleMetaObjectInfo, lir);
}
-2
View File
@@ -34,7 +34,6 @@ OptimizationInfo::initNormalOptimizationInfo()
rangeAnalysis_ = true;
reordering_ = true;
sincos_ = true;
sink_ = true;
registerAllocator_ = RegisterAllocator_Backtracking;
@@ -69,7 +68,6 @@ OptimizationInfo::initWasmOptimizationInfo()
eliminateRedundantChecks_ = false;
scalarReplacement_ = false; // wasm has no objects.
sincos_ = false;
sink_ = false;
}
uint32_t
-7
View File
@@ -86,9 +86,6 @@ class OptimizationInfo
// Toggles whether sincos is used.
bool sincos_;
// Toggles whether sink is used.
bool sink_;
// Describes which register allocator to use.
IonRegisterAllocator registerAllocator_;
@@ -194,10 +191,6 @@ class OptimizationInfo
return sincos_ && !JitOptions.disableSincos;
}
bool sinkEnabled() const {
return sink_ && !JitOptions.disableSink;
}
bool eaaEnabled() const {
return eaa_ && !JitOptions.disableEaa;
}
-3
View File
@@ -130,9 +130,6 @@ DefaultJitOptions::DefaultJitOptions()
SET_DEFAULT(disableSincos, true);
#endif
// Toggles whether sink code motion is globally disabled.
SET_DEFAULT(disableSink, true);
// Whether functions are compiled immediately.
SET_DEFAULT(eagerCompilation, false);
-1
View File
@@ -63,7 +63,6 @@ struct DefaultJitOptions
bool disableCacheIR;
bool disableSharedStubs;
bool disableSincos;
bool disableSink;
bool eagerCompilation;
bool forceInlineCaches;
bool limitScriptSize;
-122
View File
@@ -44,9 +44,6 @@ CommonDominator(MBasicBlock* commonDominator, MBasicBlock* defBlock)
bool
Sink(MIRGenerator* mir, MIRGraph& graph)
{
TempAllocator& alloc = graph.alloc();
bool sinkEnabled = mir->optimizationInfo().sinkEnabled();
for (PostorderIterator block = graph.poBegin(); block != graph.poEnd(); block++) {
if (mir->shouldCancel("Sink"))
return false;
@@ -106,125 +103,6 @@ Sink(MIRGenerator* mir, MIRGraph& graph)
JitSpewDef(JitSpew_Sink, " No live uses, recover the instruction on bailout\n", ins);
continue;
}
// This guard is temporarly moved here as the above code deals with
// Dead Code elimination, which got moved into this Sink phase, as
// the Dead Code elimination used to move instructions with no-live
// uses to the bailout path.
if (!sinkEnabled)
continue;
// To move an effectful instruction, we would have to verify that the
// side-effect is not observed. In the mean time, we just inhibit
// this optimization on effectful instructions.
if (ins->isEffectful())
continue;
// If all the uses are under a loop, we might not want to work
// against LICM by moving everything back into the loop, but if the
// loop is it-self inside an if, then we still want to move the
// computation under this if statement.
while (block->loopDepth() < usesDominator->loopDepth()) {
MOZ_ASSERT(usesDominator != usesDominator->immediateDominator());
usesDominator = usesDominator->immediateDominator();
}
// Only move instructions if there is a branch between the dominator
// of the uses and the original instruction. This prevent moving the
// computation of the arguments into an inline function if there is
// no major win.
MBasicBlock* lastJoin = usesDominator;
while (*block != lastJoin && lastJoin->numPredecessors() == 1) {
MOZ_ASSERT(lastJoin != lastJoin->immediateDominator());
MBasicBlock* next = lastJoin->immediateDominator();
if (next->numSuccessors() > 1)
break;
lastJoin = next;
}
if (*block == lastJoin)
continue;
// Skip to the next instruction if we cannot find a common dominator
// for all the uses of this instruction, or if the common dominator
// correspond to the block of the current instruction.
if (!usesDominator || usesDominator == *block)
continue;
// Only instruction which can be recovered on bailout and which are
// sinkable can be moved into blocks which are below while filling
// the resume points with a clone which is recovered on bailout.
// If the instruction has live uses and if it is clonable, then we
// can clone the instruction for all non-dominated uses and move the
// instruction into the block which is dominating all live uses.
if (!ins->canClone())
continue;
// If the block is a split-edge block, which is created for folding
// test conditions, then the block has no resume point and has
// multiple predecessors. In such case, we cannot safely move
// bailing instruction to these blocks as we have no way to bailout.
if (!usesDominator->entryResumePoint() && usesDominator->numPredecessors() != 1)
continue;
JitSpewDef(JitSpew_Sink, " Can Clone & Recover, sink instruction\n", ins);
JitSpew(JitSpew_Sink, " into Block %u", usesDominator->id());
// Copy the arguments and clone the instruction.
MDefinitionVector operands(alloc);
for (size_t i = 0, end = ins->numOperands(); i < end; i++) {
if (!operands.append(ins->getOperand(i)))
return false;
}
MInstruction* clone = ins->clone(alloc, operands);
ins->block()->insertBefore(ins, clone);
clone->setRecoveredOnBailout();
// We should not update the producer of the entry resume point, as
// it cannot refer to any instruction within the basic block excepts
// for Phi nodes.
MResumePoint* entry = usesDominator->entryResumePoint();
// Replace the instruction by its clone in all the resume points /
// recovered-on-bailout instructions which are not in blocks which
// are dominated by the usesDominator block.
for (MUseIterator i(ins->usesBegin()), e(ins->usesEnd()); i != e; ) {
MUse* use = *i++;
MNode* consumer = use->consumer();
// If the consumer is a Phi, then we look for the index of the
// use to find the corresponding predecessor block, which is
// then used as the consumer block.
MBasicBlock* consumerBlock = consumer->block();
if (consumer->isDefinition() && consumer->toDefinition()->isPhi()) {
consumerBlock = consumerBlock->getPredecessor(
consumer->toDefinition()->toPhi()->indexOf(use));
}
// Keep the current instruction for all dominated uses, except
// for the entry resume point of the block in which the
// instruction would be moved into.
if (usesDominator->dominates(consumerBlock) &&
(!consumer->isResumePoint() || consumer->toResumePoint() != entry))
{
continue;
}
use->replaceProducer(clone);
}
// As we move this instruction in a different block, we should
// verify that we do not carry over a resume point which would refer
// to an outdated state of the control flow.
if (ins->resumePoint())
ins->clearResumePoint();
// Now, that all uses which are not dominated by usesDominator are
// using the cloned instruction, we can safely move the instruction
// into the usesDominator block.
MInstruction* at = usesDominator->safeInsertTop(nullptr, MBasicBlock::IgnoreRecover);
block->moveBefore(at, ins);
}
}
+8
View File
@@ -8,6 +8,14 @@
#include "jit/x86-shared/BaseAssembler-x86-shared.h"
// Jihad Browser: GCC 9+ -Wformat-overflow raises false positives on the debug
// spew() format strings below (it deduces a null %s arg via value-range
// analysis). js/src forces -Werror=format, which re-escalates this even when
// downgraded on the command line, so silence the diagnostic at the source.
#if defined(__GNUC__) && !defined(__clang__)
# pragma GCC diagnostic ignored "-Wformat-overflow"
#endif
namespace js {
namespace jit {
-11
View File
@@ -7709,15 +7709,6 @@ SetContextOptions(JSContext* cx, const OptionParser& op)
return OptionFailure("ion-sincos", str);
}
if (const char* str = op.getStringOption("ion-sink")) {
if (strcmp(str, "on") == 0)
jit::JitOptions.disableSink = false;
else if (strcmp(str, "off") == 0)
jit::JitOptions.disableSink = true;
else
return OptionFailure("ion-sink", str);
}
if (const char* str = op.getStringOption("ion-loop-unrolling")) {
if (strcmp(str, "on") == 0)
jit::JitOptions.disableLoopUnrolling = false;
@@ -8093,8 +8084,6 @@ main(int argc, char** argv, char** envp)
|| !op.addStringOption('\0', "ion-sincos", "on/off",
"Replace sin(x)/cos(x) to sincos(x) (default: off, on to enable)")
#endif
|| !op.addStringOption('\0', "ion-sink", "on/off",
"Sink code motion (default: off, on to enable)")
|| !op.addStringOption('\0', "ion-loop-unrolling", "on/off",
"Loop unrolling (default: off, on to enable)")
|| !op.addStringOption('\0', "ion-instruction-reordering", "on/off",
+19
View File
@@ -673,6 +673,13 @@ nsXULPopupManager::ShowMenu(nsIContent *aMenu,
bool aSelectFirstItem,
bool aAsynchronous)
{
// JIHAD popup instrumentation: the toolbarbutton type="menu" path (about:addons
// utils menu) enters here; if this line never fires, the DOM activation upstream
// (XUL button command/mousedown handling) is where the tap died.
if (getenv("JIHAD_OFFSCREEN")) {
fprintf(stderr, "[jihad-popup] ShowMenu menu=%p async=%d\n",
(void*)aMenu, (int)aAsynchronous);
}
// generate any template content first. Otherwise, the menupopup may not
// have been created yet.
if (aMenu) {
@@ -897,6 +904,18 @@ nsXULPopupManager::ShowPopupCallback(nsIContent* aPopup,
nsPopupType popupType = aPopupFrame->PopupType();
bool ismenu = (popupType == ePopupTypeMenu);
// JIHAD popup instrumentation (2026-08-02): EVERY popup that actually opens funnels
// through here. Silent until now — "menu never opened" vs "opened but painted
// nowhere" were indistinguishable in the headless daemon.
if (getenv("JIHAD_OFFSCREEN")) {
nsRect r = aPopupFrame->GetRect();
fprintf(stderr, "[jihad-popup] ShowPopupCallback type=%d ctx=%d frame=%p rect=%d,%d %dx%d hasView=%d hasWidget=%d\n",
(int)popupType, (int)aIsContextMenu, (void*)aPopupFrame,
r.x, r.y, r.width, r.height,
(int)aPopupFrame->HasView(),
(int)(aPopupFrame->GetView() && aPopupFrame->GetView()->HasWidget()));
}
nsMenuChainItem* item =
new nsMenuChainItem(aPopupFrame, aIsContextMenu, popupType);
if (!item)
+63 -2
View File
@@ -40,6 +40,9 @@
X(pa_operation_get_state) \
X(pa_operation_unref) \
X(pa_proplist_gets) \
X(pa_proplist_new) \
X(pa_proplist_sets) \
X(pa_proplist_free) \
X(pa_rtclock_now) \
X(pa_stream_begin_write) \
X(pa_stream_cancel_write) \
@@ -53,6 +56,7 @@
X(pa_stream_get_state) \
X(pa_stream_get_time) \
X(pa_stream_new) \
X(pa_stream_new_with_proplist) \
X(pa_stream_set_state_callback) \
X(pa_stream_set_write_callback) \
X(pa_stream_unref) \
@@ -114,8 +118,20 @@ struct cubeb_stream {
int shutdown;
float volume;
cubeb_state state;
int jihad_active; /* Jihad: counted in jihad_pulse_active_count while this stream is playing */
};
/* Jihad/webOS: number of currently-PLAYING (uncorked) output streams. The daemon
(render/goanna/BrowserPageGoanna) polls jihad_pulse_active_streams() and, on 0<->N transitions,
runs $JIHAD_STATE_DIR/audio-{on,off}.sh to hold the audiod media scenario + force the speaker
mixer, so engine media audio respects the system volume and can reach the built-in speaker (the
media.role set below gets the stream onto the media policy path in the first place). Weak-linked
from the daemon; on desktop nothing reads it and it is inert. */
static int jihad_pulse_active_count = 0;
/* visibility("default"): libxul is built -fvisibility=hidden, so export it explicitly (same as the
MOZ_EXPORT on jihad_plugin_frame_seq) or the daemon's weak extern resolves to null. */
__attribute__((visibility("default"))) int jihad_pulse_active_streams(void) { return jihad_pulse_active_count; }
static const float PULSE_NO_GAIN = -1.0;
enum cork_state {
@@ -680,7 +696,41 @@ create_pa_stream(cubeb_stream * stm,
ss.rate = stream_params->rate;
ss.channels = stream_params->channels;
*pa_stm = WRAP(pa_stream_new)(stm->context->context, stream_name, &ss, NULL);
/* Jihad/webOS: module-palm-policy powers the hardware codec route (and the built-in speaker)
only for a stream it CLASSIFIES as media, via a pa_proplist property our stream otherwise
lacks (see impl-audio-backend.md). The exact property/value is not yet pinned, so read
"key=value" lines from a WRITABLE file, $JIHAD_STATE_DIR/pulse.props, and set each on the
stream proplist — this lets the routing property be tuned on-device without a libxul rebuild.
With no file present, default to media.role=music. On desktop JIHAD_STATE_DIR is unset, no
file is read, and the default is a harmless standard PulseAudio role. */
pa_proplist * pl = WRAP(pa_proplist_new)();
int have_props = 0;
char const * sd = getenv("JIHAD_STATE_DIR");
if (sd && *sd) {
char path[512];
snprintf(path, sizeof(path), "%s/pulse.props", sd);
FILE * pf = fopen(path, "r");
if (pf) {
char line[256];
while (fgets(line, sizeof(line), pf)) {
char * nl = strchr(line, '\n'); if (nl) { *nl = '\0'; }
if (line[0] == '\0' || line[0] == '#') { continue; }
char * eq = strchr(line, '=');
if (eq) { *eq = '\0'; WRAP(pa_proplist_sets)(pl, line, eq + 1); have_props = 1; }
}
fclose(pf);
}
}
if (!have_props) {
/* Default: classify as media so the stream takes the webOS media-policy path (the pmedia
virtual sink) instead of sitting anonymously on pcm_output at a fixed 100%. That classification
is what lets the daemon's audio-on.sh hold the audiod media scenario (system-volume-respecting)
and force the speaker route on top. See impl-audio-backend.md. Override/disable via the props
file. */
WRAP(pa_proplist_sets)(pl, "media.role", "music");
}
*pa_stm = WRAP(pa_stream_new_with_proplist)(stm->context->context, stream_name, &ss, NULL, pl);
WRAP(pa_proplist_free)(pl);
return (*pa_stm == NULL) ? CUBEB_ERROR : CUBEB_OK;
}
@@ -752,8 +802,16 @@ pulse_stream_init(cubeb * context,
WRAP(pa_stream_set_write_callback)(stm->output_stream, stream_write_callback, stm);
battr = set_buffering_attribute(latency_frames, &stm->output_sample_spec);
/* Jihad/webOS: module-palm-policy powers the hardware codec route only for a stream created on
a named virtual sink (pmedia); a NULL/default sink lands on pcm_output and is muted to 0%.
When no explicit device was requested, honour JIHAD_PULSE_SINK so the device build can
target "pmedia". No effect on desktop (env unset -> NULL -> default sink, upstream behaviour). */
char const * jihad_out_sink = (char const *) output_device;
if (!jihad_out_sink) {
jihad_out_sink = getenv("JIHAD_PULSE_SINK");
}
WRAP(pa_stream_connect_playback)(stm->output_stream,
output_device,
jihad_out_sink,
&battr,
PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_INTERPOLATE_TIMING |
PA_STREAM_START_CORKED | PA_STREAM_ADJUST_LATENCY,
@@ -821,6 +879,7 @@ static void
pulse_stream_destroy(cubeb_stream * stm)
{
stream_cork(stm, CORK);
if (stm->jihad_active) { stm->jihad_active = 0; if (jihad_pulse_active_count > 0) jihad_pulse_active_count--; }
WRAP(pa_threaded_mainloop_lock)(stm->context->mainloop);
if (stm->output_stream) {
@@ -864,6 +923,7 @@ pulse_stream_start(cubeb_stream * stm)
{
stm->shutdown = 0;
stream_cork(stm, UNCORK | NOTIFY);
if (stm->output_stream && !stm->jihad_active) { stm->jihad_active = 1; jihad_pulse_active_count++; }
if (stm->output_stream && !stm->input_stream) {
/* On output only case need to manually call user cb once in order to make
@@ -890,6 +950,7 @@ pulse_stream_stop(cubeb_stream * stm)
WRAP(pa_threaded_mainloop_unlock)(stm->context->mainloop);
stream_cork(stm, CORK | NOTIFY);
if (stm->jihad_active) { stm->jihad_active = 0; if (jihad_pulse_active_count > 0) jihad_pulse_active_count--; }
return CUBEB_OK;
}
+76
View File
@@ -0,0 +1,76 @@
PNG REFERENCE LIBRARY AUTHORS
=============================
This is the list of PNG Reference Library ("libpng") Contributing
Authors, for copyright and licensing purposes.
* Adam Richter
* Alexander Smorkalov
* Andreas Dilger
* Chris Blume
* Cosmin Truta
* Dave Martindale
* Eric S. Raymond
* Gilles Vollant
* Glenn Randers-Pehrson
* Greg Roelofs
* Guy Eric Schalnat
* Halil Oktay
* James Yu
* John Bowler
* Joshua Inscoe
* Kevin Bracey
* Lucas Chollet
* Magnus Holmgren
* Mandar Sahastrabuddhe
* Manfred Schlaegl
* Mans Rullgard
* Matt Sarett
* Mike Klein
* Mohammad Seet
* Pascal Massimino
* Paul Schmidt
* Petr Simecek
* Philippe Antoine
* Qiang Zhou
* Sam Bushell
* Samuel Williams
* Simon-Pierre Cadieux
* Taegu Ha (하태구)
* Tim Wegner
* Tobias Stoeckmann
* Tom Lane
* Tom Tanner
* Vadim Barkov
* Willem van Schaik
* Yuelin Wang (王跃林)
* Zhijie Liang
* Apple Inc.
- Zixu Wang (王子旭)
* Arm Holdings
- Richard Townsend
* Google LLC
- Dan Field
- Dragoș Tiselice
- Leon Scroggins III
- Matt Sarett
- Mike Klein
- Sami Boukortt
- Wan-Teh Chang
* Loongson Technology Corporation Ltd.
- GuXiWei (顾希伟)
- JinBo (金波)
- ZhangLixia (张利霞)
* Samsung Group
- Filip Wasil
* SpacemiT Hangzhou Technology, Co.
- Liang Junzhao (梁俊钊)
The build projects, the build scripts, the test scripts, and other
files in the "projects", "scripts" and "tests" directories, have
other copyright owners, but are released under the libpng license.
Some files in the "ci" and "contrib" directories, as well as some
of the tools-generated files that are distributed with libpng, have
other copyright owners, and are released under other open source
licenses.
+656 -26
View File
@@ -943,7 +943,7 @@ Version 1.0.8 [July 24, 2000]
Version 1.0.9beta1 [November 10, 2000]
Fixed typo in scripts/makefile.hpux
Updated makevms.com in scripts and contrib/* and contrib/* (Martin Zinser)
Fixed seqence-point bug in contrib/pngminus/png2pnm (Martin Zinser)
Fixed sequence-point bug in contrib/pngminus/png2pnm (Martin Zinser)
Changed "cdrom.com" in documentation to "libpng.org"
Revised pnggccrd.c to get it all working, and updated makefile.gcmmx (Greg).
Changed type of "params" from voidp to png_voidp in png_read|write_png().
@@ -1454,7 +1454,7 @@ Version 1.2.6beta4 [July 28, 2004]
sequential read support.
Added some "#if PNG_WRITE_SUPPORTED" blocks.
Added #ifdef to remove some redundancy in png_malloc_default().
Use png_malloc instead of png_zalloc to allocate the pallete.
Use png_malloc instead of png_zalloc to allocate the palette.
Version 1.0.16rc1 and 1.2.6rc1 [August 4, 2004]
Fixed buffer overflow vulnerability (CVE-2004-0597) in png_handle_tRNS().
@@ -2296,7 +2296,7 @@ Version 1.4.0beta58 [May 14, 2009]
Clarified usage of sig_bit versus sig_bit_p in example.c (Vincent Torri)
Version 1.4.0beta59 [May 15, 2009]
Reformated sources in libpng style (3-space intentation, comment format)
Reformatted sources in libpng style (3-space indentation, comment format)
Fixed typo in libpng docs (PNG_FILTER_AVE should be PNG_FILTER_AVG)
Added sections about the git repository and our coding style to the
documentation
@@ -2662,7 +2662,7 @@ Version 1.4.1beta06 [January 28, 2010]
Version 1.4.1beta07 [February 6, 2010]
Folded some long lines in the source files.
Added defineable PNG_USER_CHUNK_CACHE_MAX, PNG_USER_CHUNK_MALLOC_MAX,
Added definable PNG_USER_CHUNK_CACHE_MAX, PNG_USER_CHUNK_MALLOC_MAX,
and a PNG_USER_LIMITS_SUPPORTED flag.
Eliminated use of png_ptr->irowbytes and reused the slot in png_ptr as
png_ptr->png_user_chunk_malloc_max.
@@ -3259,7 +3259,7 @@ Version 1.5.2beta01 [February 13, 2011]
Revised PNG_EXPORTA macro to not use an empty parameter, to accommodate the
old VisualC++ preprocessor.
Turned on interlace handling in png_read_png().
Fixed gcc pendantic warnings.
Fixed gcc pedantic warnings.
Handle longjmp in Cygwin.
Fixed png_get_current_row_number() in the interlaced case.
Cleaned up ALPHA flags and transformations.
@@ -3359,7 +3359,7 @@ Version 1.5.3beta05 [May 6, 2011]
Pass "" instead of '\0' to png_default_error() in png_err(). This mistake
was introduced in libpng-1.2.20beta01. This fixes CVE-2011-2691.
Added PNG_WRITE_OPTIMIZE_CMF_SUPPORTED macro to make the zlib "CMF" byte
optimization configureable.
optimization configurable.
IDAT compression failed if preceded by a compressed text chunk (bug
introduced in libpng-1.5.3beta01-02). This was because the attempt to
reset the zlib stream in png_write_IDAT happened after the first IDAT
@@ -3643,7 +3643,7 @@ Version 1.5.6beta05 [October 12, 2011]
Fixed bug in png_write_chunk_header() debug print, introduced in 1.5.6beta01.
Version 1.5.6beta06 [October 17, 2011]
Removed two redundant tests for unitialized row.
Removed two redundant tests for uninitialized row.
Fixed a relatively harmless memory overwrite in compressed text writing
with a 1 byte zlib buffer.
Add ability to call png_read_update_info multiple times to pngvalid.c.
@@ -3689,7 +3689,7 @@ Version 1.5.7beta01 [November 4, 2011]
crash. The pngmem.c implementation of png_malloc() included a cast
to png_size_t which would fail on large allocations on 16-bit systems.
Fix for the preprocessor of the Intel C compiler. The preprocessor
splits adjacent @ signs with a space; this changes the concatentation
splits adjacent @ signs with a space; this changes the concatenation
token from @-@-@ to PNG_JOIN; that should work with all compiler
preprocessors.
Paeth filter speed improvements from work by Siarhei Siamashka. This
@@ -3735,7 +3735,7 @@ Version 1.5.7beta03 [November 17, 2011]
gray (on palette) itself.
Fixes for C++ compilation using g++ When libpng source is compiled
using g++. The compiler imposes C++ rules on the C source; thus it
is desireable to make the source work with either C or C++ rules
is desirable to make the source work with either C or C++ rules
without throwing away useful error information. This change adds
png_voidcast to allow C semantic (void*) cases or the corresponding
C++ static_cast operation, as appropriate.
@@ -3887,7 +3887,7 @@ Version 1.6.0beta06 [January 24, 2012]
Version 1.6.0beta07 [January 28, 2012]
Eliminated Intel icc/icl compiler warnings. The Intel (GCC derived)
compiler issues slightly different warnings from those issued by the
current vesions of GCC. This eliminates those warnings by
current versions of GCC. This eliminates those warnings by
adding/removing casts and small code rewrites.
Updated configure.ac from autoupdate: added --enable-werror option.
Also some layout regularization and removal of introduced tab characters
@@ -3920,7 +3920,7 @@ Version 1.6.0beta08 [February 1, 2012]
version checking to configure.ac
Improved pngstest speed by not doing redundant tests and add const to
the background parameter of png_image_finish_read. The --background
option is now done automagically only when required, so that commandline
option is now done automagically only when required, so that command-line
option no longer exists.
Cleaned up pngpriv.h to consistently declare all functions and data.
Also eliminated PNG_CONST_DATA, which is apparently not needed but we
@@ -4053,7 +4053,7 @@ Version 1.6.0beta16 [March 6, 2012]
(in fact this is harmless, but the PNG data produced may be sub-optimal).
Version 1.6.0beta17 [March 10, 2012]
Fixed PNG_LIBPNG_BUILD_BASE_TYPE definition.
Fixed PNG_LIBPNG_BUILD_BASE_TYPE definition.
Reject all iCCP chunks after the first, even if the first one is invalid.
Deflate/inflate was reworked to move common zlib calls into single
functions [rw]util.c. A new shared keyword check routine was also added
@@ -4061,7 +4061,7 @@ Version 1.6.0beta17 [March 10, 2012]
possible to call png_inflate() incrementally. A warning is no longer
issued if the language tag or translated keyword in the iTXt chunk
has zero length.
If benign errors are disabled use maximum window on ancilliary inflate.
If benign errors are disabled use maximum window on ancillary inflate.
This works round a bug introduced in 1.5.4 where compressed ancillary
chunks could end up with a too-small windowBits value in the deflate
header.
@@ -4176,7 +4176,7 @@ Version 1.6.0beta27 [August 11, 2012]
declared even though the functions are never actually defined. This
change provides a dummy definition so that the declarations work, yet any
implementation will fail to compile because of an incomplete type.
Re-eliminated the use of strcpy() in pngtest.c. An unncessary use of
Re-eliminated the use of strcpy() in pngtest.c. An unnecessary use of
strcpy() was accidentally re-introduced in libpng16; this change replaces
it with strncpy().
Eliminated use of png_sizeof(); use sizeof() instead.
@@ -4309,7 +4309,7 @@ Version 1.6.0beta31 [November 1, 2012]
resulting in VS2010 having to update the files.
Removed non-working ICC profile support code that was mostly added to
libpng-1.6.0beta29 and beta30. There was too much code for too little
gain; implementing full ICC color correction may be desireable but is left
gain; implementing full ICC color correction may be desirable but is left
up to applications.
Version 1.6.0beta32 [November 25, 2012]
@@ -4592,7 +4592,7 @@ Version 1.6.3beta07 [June 8, 2013]
the optimizations ('check' vs 'api') are exposed in the public header files
except that the new setting PNG_ARM_NEON_OPT documents how libpng makes the
decision about whether or not to use the optimizations.
Protect symbol prefixing against CC/CPPFLAGS/CFLAGS useage.
Protect symbol prefixing against CC/CPPFLAGS/CFLAGS usage.
Previous iOS/Xcode fixes for the ARM NEON optimizations moved the test
on __ARM_NEON__ from configure time to compile time. This breaks symbol
prefixing because the definition of the special png_init_filter_functions
@@ -4963,7 +4963,7 @@ Version 1.6.13beta01 [July 4, 2014]
Changed "if defined(__ARM_NEON__)" to
"if (defined(__ARM_NEON__) || defined(__ARM_NEON))" (James Wu).
Fixed clang no-warning builds: png_digit was defined but never used.
Version 1.6.13beta02 [July 21, 2014]
Fixed an incorrect separator ("/" should be "\") in scripts/makefile.vcwin32
(bug report from Wolfgang S. Kechel). Bug was introduced in libpng-1.6.11.
@@ -5454,7 +5454,7 @@ Version 1.6.21beta01 [December 11, 2015]
Version 1.6.21beta02 [December 14, 2015]
Moved png_check_keyword() from pngwutil.c to pngset.c
Removed LE/BE dependencies in pngvalid, to 'fix' the current problem
in the BigEndian tests by not testing it, making the BE code the same
in the BigEndian tests by not testing it, making the BE code the same
as the LE version.
Fixes to pngvalid for various reduced build configurations (eliminate unused
statics) and a fix for the case in rgb_to_gray when the digitize option
@@ -5518,7 +5518,7 @@ Version 1.6.22beta03 [March 9, 2016]
Added a common-law trademark notice and export control information
to the LICENSE file, png.h, and the man page.
Restored "& 0xff" in png_save_uint_16() and png_save_uint_32() that
were accidentally removed from libpng-1.6.17.
were accidentally removed from libpng-1.6.17.
Changed PNG_INFO_cHNK and PNG_FREE_cHNK from 0xnnnn to 0xnnnnU in png.h
(Robert C. Seacord).
Removed dubious "#if INT_MAX" test from png.h that was added to
@@ -5635,7 +5635,7 @@ Version 1.6.24beta02 [June 23, 2016]
to All and adds a list of the warnings that need to be turned off. This is
semi-documentary; the intent is to tell libpng users which warnings have
been examined and judged non-fixable at present. The warning about
structure padding is fixable, but it would be a signficant change (moving
structure padding is fixable, but it would be a significant change (moving
structure members around).
Version 1.6.24beta03 [July 4, 2016]
@@ -5754,11 +5754,641 @@ Version 1.6.26 [October 20, 2016]
Cosmetic change, "ptr != 0" to "ptr != NULL" in png.c and pngrutil.c
Despammed email addresses (replaced "@" with " at ").
Send comments/corrections/commendations to png-mng-implement at lists.sf.net
(subscription required; visit
https://lists.sourceforge.net/lists/listinfo/png-mng-implement
to subscribe)
or to glennrp at users.sourceforge.net
Version 1.6.27beta01 [November 2, 2016]
Restrict the new ADLER32-skipping to IDAT chunks. It broke iCCP chunk
handling: an erroneous iCCP chunk would throw a png_error and reject the
entire PNG image instead of rejecting just the iCCP chunk with a warning,
if built with zlib-1.2.8.1.
Glenn R-P
Version 1.6.27rc01 [December 27, 2016]
Control ADLER32 checking with new PNG_IGNORE_ADLER32 option. Fixes
an endless loop when handling erroneous ADLER32 checksums; bug
introduced in libpng-1.6.26.
Removed the use of a macro containing the pre-processor 'defined'
operator. It is unclear whether this is valid; a macro that
"generates" 'defined' is not permitted, but the use of the word
"generates" within the C90 standard seems to imply more than simple
substitution of an expression itself containing a well-formed defined
operation.
Added ARM support to CMakeLists.txt (Andreas Franek).
Version 1.6.27 [December 29, 2016]
Fixed a potential null pointer dereference in png_set_text_2() (bug report
and patch by Patrick Keshishian, CVE-2016-10087).
Version 1.6.28rc01 [January 3, 2017]
Fixed arm/aarch64 detection in CMakeLists.txt (Gianfranco Costamagna).
Added option to Cmake build allowing a custom location of zlib to be
specified in a scenario where libpng is being built as a subproject
alongside zlib by another project (Sam Serrels).
Changed png_ptr->options from a png_byte to png_uint_32, to accommodate
up to 16 options.
Version 1.6.28rc02 [January 4, 2017]
Added "include(GNUInstallDirs)" to CMakeLists.txt (Gianfranco Costamagna).
Moved SSE2 optimization code into the main libpng source directory.
Configure libpng with "configure --enable-intel-sse" or compile
libpng with "-DPNG_INTEL_SSE" in CPPFLAGS to enable it.
Version 1.6.28rc03 [January 4, 2017]
Backed out the SSE optimization and last CMakeLists.txt to allow time for QA.
Version 1.6.28 [January 5, 2017]
No changes.
Version 1.6.29beta01 [January 12, 2017]
Readded "include(GNUInstallDirs)" to CMakeLists.txt (Gianfranco Costamagna).
Moved SSE2 optimization code into the main libpng source directory.
Configure libpng with "configure --enable-intel-sse" or compile
libpng with "-DPNG_INTEL_SSE" in CPPFLAGS to enable it.
Simplified conditional compilation in pngvalid.c, for AIX (Michael Felt).
Version 1.6.29beta02 [February 22, 2017]
Avoid conditional directives that break statements in pngrutil.c (Romero
Malaquias)
The contrib/examples/pngtopng.c recovery code was in the wrong "if"
branches; the comments were correct.
Added code for PowerPC VSX optimisation (Vadim Barkov).
Version 1.6.29beta03 [March 1, 2017]
Avoid potential overflow of shift operations in png_do_expand() (Aaron Boxer).
Change test ZLIB_VERNUM >= 0x1281 to ZLIB_VERNUM >= 0x1290 in pngrutil.c
because Solaris 11 distributes zlib-1.2.8.f that is older than 1.2.8.1,
as suggested in zlib FAQ, item 24.
Suppress clang warnings about implicit sign changes in png.c
Version 1.6.29 [March 16, 2017]
No changes.
Version 1.6.30beta01 [April 1, 2017]
Added missing "$(CPPFLAGS)" to the compile line for c.pic.o in
makefile.linux and makefile.solaris-x86 (Cosmin).
Revised documentation of png_get_error_ptr() in the libpng manual.
Silence clang -Wcomma and const drop warnings (Viktor Szakats).
Update Sourceforge URLs in documentation (https instead of http).
Version 1.6.30beta02 [April 22, 2017]
Document need to check for integer overflow when allocating a pixel
buffer for multiple rows in contrib/gregbook, contrib/pngminus,
example.c, and in the manual (suggested by Jaeseung Choi). This
is similar to the bug reported against pngquant in CVE-2016-5735.
Removed reference to the obsolete PNG_SAFE_LIMITS macro in the documentation.
Version 1.6.30beta03 [May 22, 2017]
Check for integer overflow in contrib/visupng and contrib/tools/genpng.
Do not double evaluate CMAKE_SYSTEM_PROCESSOR in CMakeLists.txt.
Test CMAKE_HOST_WIN32 instead of WIN32 in CMakeLists.txt.
Fix some URL in documentation.
Version 1.6.30beta04 [June 7, 2017]
Avoid writing an empty IDAT when the last IDAT exactly fills the
compression buffer (bug report by Brian Baird). This bug was
introduced in libpng-1.6.0.
Version 1.6.30rc01 [June 14, 2017]
No changes.
Version 1.6.30rc02 [June 25, 2017]
Update copyright year in pnglibconf.h, make ltmain.sh executable.
Add a reference to the libpng.download site in README.
Version 1.6.30 [June 28, 2017]
No changes.
Version 1.6.31beta01 [July 5, 2017]
Guard the definition of _POSIX_SOURCE in pngpriv.h (AIX already defines it;
bug report by Michael Felt).
Revised pngpriv.h to work around failure to compile arm/filter_neon.S
("typedef" directive is unrecognized by the assembler). The problem
was introduced in libpng-1.6.30beta01.
Added "Requires: zlib" to libpng.pc.in (Pieter Neerincx).
Added special case for FreeBSD in arm/filter_neon.S (Maya Rashish).
Version 1.6.31beta02 [July 8, 2017]
Added instructions for disabling hardware optimizations in INSTALL.
Added "--enable-hardware-optimizations" configuration flag to enable
or disable all hardware optimizations with one flag.
Version 1.6.31beta03 [July 9, 2017]
Updated CMakeLists.txt to add INTEL_SSE and MIPS_MSA platforms.
Changed "int" to "png_size_t" in intel/filter_sse2.c to prevent
possible integer overflow (Bug report by John Bowler).
Quieted "declaration after statement" warnings in intel/filter_sse2.c.
Added scripts/makefile-linux-opt, which has hardware optimizations enabled.
Version 1.6.31beta04 [July 11, 2017]
Removed one of the GCC-7.1.0 'strict-overflow' warnings that result when
integers appear on both sides of a compare. Worked around the others by
forcing the strict-overflow setting in the relevant functions to a level
where they are not reported (John Bowler).
Changed "FALL THROUGH" comments to "FALLTHROUGH" because GCC doesn't like
the space.
Worked around some C-style casts from (void*) because g++ 5.4.0 objects
to them.
Increased the buffer size for 'sprint' to pass the gcc 7.1.0 'sprint
overflow' check that is on by default with -Wall -Wextra.
Version 1.6.31beta05 [July 13, 2017]
Added eXIf chunk support.
Version 1.6.31beta06 [July 17, 2017]
Added a minimal eXIf chunk (with Orientation and FocalLengthIn35mmFilm
tags) to pngtest.png.
Version 1.6.31beta07 [July 18, 2017]
Revised the eXIf chunk in pngtest.png to fix "Bad IFD1 Directory" warning.
Version 1.6.31rc01 [July 19, 2017]
No changes.
Version 1.6.31rc02 [July 25, 2017]
Fixed typo in example.c (png_free_image should be png_image_free) (Bug
report by John Smith)
Version 1.6.31 [July 27, 2017]
No changes.
Version 1.6.32beta01 [July 31, 2017]
Avoid possible NULL dereference in png_handle_eXIf when benign_errors
are allowed. Avoid leaking the input buffer "eXIf_buf".
Eliminated png_ptr->num_exif member from pngstruct.h and added num_exif
to arguments for png_get_eXIf() and png_set_eXIf().
Added calls to png_handle_eXIf(() in pngread.c and png_write_eXIf() in
pngwrite.c, and made various other fixes to png_write_eXIf().
Changed name of png_get_eXIF and png_set_eXIf() to png_get_eXIf_1() and
png_set_eXIf_1(), respectively, to avoid breaking API compatibility
with libpng-1.6.31.
Version 1.6.32beta02 [August 1, 2017]
Updated contrib/libtests/pngunknown.c with eXIf chunk.
Version 1.6.32beta03 [August 2, 2017]
Initialized btoa[] in pngstest.c
Stop memory leak when returning from png_handle_eXIf() with an error
(Bug report from the OSS-fuzz project).
Version 1.6.32beta04 [August 2, 2017]
Replaced local eXIf_buf with info_ptr->eXIf_buf in png_handle_eXIf().
Update libpng.3 and libpng-manual.txt about eXIf functions.
Version 1.6.32beta05 [August 2, 2017]
Restored png_get_eXIf() and png_set_eXIf() to maintain API compatibility.
Version 1.6.32beta06 [August 2, 2017]
Removed png_get_eXIf_1() and png_set_eXIf_1().
Version 1.6.32beta07 [August 3, 2017]
Check length of all chunks except IDAT against user limit to fix an
OSS-fuzz issue (Fixes CVE-2017-12652).
Version 1.6.32beta08 [August 3, 2017]
Check length of IDAT against maximum possible IDAT size, accounting
for height, rowbytes, interlacing and zlib/deflate overhead.
Restored png_get_eXIf_1() and png_set_eXIf_1(), because strlen(eXIf_buf)
does not work (the eXIf chunk data can contain zeroes).
Version 1.6.32beta09 [August 3, 2017]
Require cmake-2.8.8 in CMakeLists.txt. Revised symlink creation,
no longer using deprecated cmake LOCATION feature (Clifford Yapp).
Fixed five-byte error in the calculation of IDAT maximum possible size.
Version 1.6.32beta10 [August 5, 2017]
Moved chunk-length check into a png_check_chunk_length() private
function (Suggested by Max Stepin).
Moved bad pngs from tests to contrib/libtests/crashers
Moved testing of bad pngs into a separate tests/pngtest-badpngs script
Added the --xfail (expected FAIL) option to pngtest.c. It writes XFAIL
in the output but PASS for the libpng test.
Require cmake-3.0.2 in CMakeLists.txt (Clifford Yapp).
Fix "const" declaration info_ptr argument to png_get_eXIf_1() and the
num_exif argument to png_get_eXIf_1() (Github Issue 171).
Version 1.6.32beta11 [August 7, 2017]
Added "eXIf" to "chunks_to_ignore[]" in png_set_keep_unknown_chunks().
Added huge_IDAT.png and empty_ancillary_chunks.png to testpngs/crashers.
Make pngtest --strict, --relax, --xfail options imply -m (multiple).
Removed unused chunk_name parameter from png_check_chunk_length().
Relocated setting free_me for eXIf data, to stop an OSS-fuzz leak.
Initialize profile_header[] in png_handle_iCCP() to fix OSS-fuzz issue.
Initialize png_ptr->row_buf[0] to 255 in png_read_row() to fix OSS-fuzz UMR.
Attempt to fix a UMR in png_set_text_2() to fix OSS-fuzz issue.
Increase minimum zlib stream from 9 to 14 in png_handle_iCCP(), to account
for the minimum 'deflate' stream, and relocate the test to a point
after the keyword has been read.
Check that the eXIf chunk has at least 2 bytes and begins with "II" or "MM".
Version 1.6.32rc01 [August 18, 2017]
Added a set of "huge_xxxx_chunk.png" files to contrib/testpngs/crashers,
one for each known chunk type, with length = 2GB-1.
Check for 0 return from png_get_rowbytes() and added some (size_t) typecasts
in contrib/pngminus/*.c to stop some Coverity issues (162705, 162706,
and 162707).
Renamed chunks in contrib/testpngs/crashers to avoid having files whose
names differ only in case; this causes problems with some platforms
(github issue #172).
Version 1.6.32rc02 [August 22, 2017]
Added contrib/oss-fuzz directory which contains files used by the oss-fuzz
project <https://github.com/google/oss-fuzz/tree/master/projects/libpng>.
Version 1.6.32 [August 24, 2017]
No changes.
Version 1.6.33beta01 [August 28, 2017]
Added PNGMINUS_UNUSED macro to contrib/pngminus/p*.c and added missing
parenthesis in contrib/pngminus/pnm2png.c (bug report by Christian Hesse).
Fixed off-by-one error in png_do_check_palette_indexes() (Bug report
by Mick P., Source Forge Issue #269).
Version 1.6.33beta02 [September 3, 2017]
Initialize png_handler.row_ptr in contrib/oss-fuzz/libpng_read_fuzzer.cc
to fix shortlived oss-fuzz issue 3234.
Compute a larger limit on IDAT because some applications write a deflate
buffer for each row (Bug report by Andrew Church).
Use current date (DATE) instead of release-date (RDATE) in last
changed date of contrib/oss-fuzz files.
Enabled ARM support in CMakeLists.txt (Bernd Kuhls).
Version 1.6.33beta03 [September 14, 2017]
Fixed incorrect typecast of some arguments to png_malloc() and
png_calloc() that were png_uint_32 instead of png_alloc_size_t
(Bug report by "irwir" in Github libpng issue #175).
Use pnglibconf.h.prebuilt when building for ANDROID with cmake (Github
issue 162, by rcdailey).
Version 1.6.33rc01 [September 20, 2017]
Initialize memory allocated by png_inflate to zero, using memset, to
stop an oss-fuzz "use of uninitialized value" detection in png_set_text_2()
due to truncated iTXt or zTXt chunk.
Initialize memory allocated by png_read_buffer to zero, using memset, to
stop an oss-fuzz "use of uninitialized value" detection in
png_icc_check_tag_table() due to truncated iCCP chunk.
Removed a redundant test (suggested by "irwir" in Github issue #180).
Version 1.6.33rc02 [September 23, 2017]
Added an interlaced version of each file in contrib/pngsuite.
Relocate new memset() call in pngrutil.c.
Removed more redundant tests (suggested by "irwir" in Github issue #180).
Add support for loading images with associated alpha in the Simplified
API (Samuel Williams).
Version 1.6.33 [September 28, 2017]
Revert contrib/oss-fuzz/libpng_read_fuzzer.cc to libpng-1.6.32 state.
Initialize png_handler.row_ptr in contrib/oss-fuzz/libpng_read_fuzzer.cc
Add end_info structure and png_read_end() to the libpng fuzzer.
Version 1.6.34 [September 29, 2017]
Removed contrib/pngsuite/i*.png; some of them caused test failures.
Version 1.6.35beta01 [March 6, 2018]
Restored 21 of the contrib/pngsuite/i*.png, which do not cause test
failures. Placed the remainder in contrib/pngsuite/interlaced/i*.png.
Added calls to png_set_*() transforms commonly used by browsers to
the fuzzer.
Removed some unnecessary brackets in pngrtran.c
Fixed miscellaneous typos (Patch by github user "luzpaz").
Change "ASM C" to "C ASM" in CMakeLists.txt
Fixed incorrect handling of bKGD chunk in sub-8-bit files (Cosmin)
Added hardware optimization directories to zip and 7z distributions.
Fixed incorrect bitmask for options.
Fixed many spelling typos.
Version 1.6.35beta02 [March 28, 2018]
Make png_get_iCCP consistent with man page (allow compression-type argument
to be NULL, bug report by Lenard Szolnoki).
Version 1.6.35 [July 15, 2018]
Replaced the remaining uses of png_size_t with size_t (Cosmin)
Fixed the calculation of row_factor in png_check_chunk_length
(reported by Thuan Pham in SourceForge issue #278)
Added missing parentheses to a macro definition
(suggested by "irwir" in GitHub issue #216)
Version 1.6.36 [December 1, 2018]
Optimized png_do_expand_palette for ARM processors.
Improved performance by around 10-22% on a recent ARM Chromebook.
(Contributed by Richard Townsend, ARM Holdings)
Fixed manipulation of machine-specific optimization options.
(Contributed by Vicki Pfau)
Used memcpy instead of manual pointer arithmetic on Intel SSE2.
(Contributed by Samuel Williams)
Fixed build errors with MSVC on ARM64.
(Contributed by Zhijie Liang)
Fixed detection of libm in CMakeLists.
(Contributed by Cameron Cawley)
Fixed incorrect creation of pkg-config file in CMakeLists.
(Contributed by Kyle Bentley)
Fixed the CMake build on Windows MSYS by avoiding symlinks.
Fixed a build warning on OpenBSD.
(Contributed by Theo Buehler)
Fixed various typos in comments.
(Contributed by "luz.paz")
Raised the minimum required CMake version from 3.0.2 to 3.1.
Removed yet more of the vestigial support for pre-ANSI C compilers.
Removed ancient makefiles for ancient systems that have been broken
across all previous libpng-1.6.x versions.
Removed the Y2K compliance statement and the export control
information.
Applied various code style and documentation fixes.
Version 1.6.37 [April 14, 2019]
Fixed a use-after-free vulnerability (CVE-2019-7317) in png_image_free.
Fixed a memory leak in the ARM NEON implementation of png_do_expand_palette.
Fixed a memory leak in pngtest.c.
Fixed two vulnerabilities (CVE-2018-14048, CVE-2018-14550) in
contrib/pngminus; refactor.
Changed the license of contrib/pngminus to MIT; refresh makefile and docs.
(Contributed by Willem van Schaik)
Fixed a typo in the libpng license v2.
(Contributed by Miguel Ojeda)
Added makefiles for AddressSanitizer-enabled builds.
Cleaned up various makefiles.
Version 1.6.38 [September 14, 2022]
Added configurations and scripts for continuous integration.
Fixed various errors in the handling of tRNS, hIST and eXIf.
Implemented many stability improvements across all platforms.
Updated the internal documentation.
Version 1.6.39 [November 20, 2022]
Changed the error handler of oversized chunks (i.e. larger than
PNG_USER_CHUNK_MALLOC_MAX) from png_chunk_error to png_benign_error.
Fixed a buffer overflow error in contrib/tools/pngfix.
Fixed a memory leak (CVE-2019-6129) in contrib/tools/pngcp.
Disabled the ARM Neon optimizations by default in the CMake file,
following the default behavior of the configure script.
Allowed configure.ac to work with the trunk version of autoconf.
Removed the support for "install" targets from the legacy makefiles;
removed the obsolete makefile.cegcc.
Cleaned up the code and updated the internal documentation.
Version 1.6.40 [June 21, 2023]
Fixed the eXIf chunk multiplicity checks.
Fixed a memory leak in pCAL processing.
Corrected the validity report about tRNS inside png_get_valid().
Fixed various build issues on *BSD, Mac and Windows.
Updated the configurations and the scripts for continuous integration.
Cleaned up the code, the build scripts, and the documentation.
Version 1.6.41 [January 24, 2024]
Added SIMD-optimized code for the LoongArch LSX hardware.
(Contributed by GuXiWei, JinBo and ZhangLixia)
Fixed the run-time discovery of MIPS MSA hardware.
(Contributed by Sui Jingfeng)
Fixed an off-by-one error in the function png_do_check_palette_indexes(),
which failed to recognize errors that might have existed in the first
column of a broken palette-encoded image. This was a benign regression
accidentally introduced in libpng-1.6.33. No pixel was harmed.
(Contributed by Adam Richter; reviewed by John Bowler)
Fixed, improved and modernized the contrib/pngminus programs, i.e.,
png2pnm.c and pnm2png.c
Removed old and peculiar portability hacks that were meant to silence
warnings issued by gcc version 7.1 alone.
(Contributed by John Bowler)
Fixed and modernized the CMake file, and raised the minimum required
CMake version from 3.1 to 3.6.
(Contributed by Clinton Ingram, Timothy Lyanguzov, Tyler Kropp, et al.)
Allowed the configure script to disable the building of auxiliary tools
and tests, thus catching up with the CMake file.
(Contributed by Carlo Bramini)
Fixed a build issue on Mac.
(Contributed by Zixu Wang)
Moved the Autoconf macro files to scripts/autoconf.
Moved the CMake files (except for the main CMakeLists.txt) to
scripts/cmake and moved the list of their contributing authors to
scripts/cmake/AUTHORS.md
Updated the CI configurations and scripts.
Relicensed the CI scripts to the MIT License.
Improved the test coverage.
(Contributed by John Bowler)
Version 1.6.42 [January 29, 2024]
Fixed the implementation of the macro function png_check_sig().
This was an API regression, introduced in libpng-1.6.41.
(Reported by Matthieu Darbois)
Fixed and updated the libpng manual.
Version 1.6.43 [February 23, 2024]
Fixed the row width check in png_check_IHDR().
This corrected a bug that was specific to the 16-bit platforms,
and removed a spurious compiler warning from the 64-bit builds.
(Reported by Jacek Caban; fixed by John Bowler)
Added eXIf chunk support to the push-mode reader in pngpread.c.
(Contributed by Chris Blume)
Added contrib/pngexif for the benefit of the users who would like
to inspect the content of eXIf chunks.
Added contrib/conftest/basic.dfa, a basic build-time configuration.
(Contributed by John Bowler)
Fixed a preprocessor condition in pngread.c that broke build-time
configurations like contrib/conftest/pngcp.dfa.
(Contributed by John Bowler)
Added CMake build support for LoongArch LSX.
(Contributed by GuXiWei)
Fixed a CMake build error that occurred under a peculiar state of the
dependency tree. This was a regression introduced in libpng-1.6.41.
(Contributed by Dan Rosser)
Marked the installed libpng headers as system headers in CMake.
(Contributed by Benjamin Buch)
Updated the build support for RISCOS.
(Contributed by Cameron Cawley)
Updated the makefiles to allow cross-platform builds to initialize
conventional make variables like AR and ARFLAGS.
Added various improvements to the CI scripts in areas like version
consistency verification and text linting.
Added version consistency verification to pngtest.c also.
Version 1.6.44 [September 12, 2024]
Hardened calculations in chroma handling to prevent overflows, and
relaxed a constraint in cHRM validation to accomodate the standard
ACES AP1 set of color primaries.
(Contributed by John Bowler)
Removed the ASM implementation of ARM Neon optimizations and updated
the build accordingly. Only the remaining C implementation shall be
used from now on, thus ensuring the support of the PAC/BTI security
features on ARM64.
(Contributed by Ross Burton and John Bowler)
Fixed the pickup of the PNG_HARDWARE_OPTIMIZATIONS option in the
CMake build on FreeBSD/amd64. This is an important performance fix
on this platform.
Applied various fixes and improvements to the CMake build.
(Contributed by Eric Riff, Benjamin Buch and Erik Scholz)
Added fuzzing targets for the simplified read API.
(Contributed by Mikhail Khachayants)
Fixed a build error involving pngtest.c under a custom config.
This was a regression introduced in a code cleanup in libpng-1.6.43.
(Contributed by Ben Wagner)
Fixed and improved the config files for AppVeyor CI and Travis CI.
Version 1.6.45 [January 7, 2025]
Added support for the cICP chunk.
(Contributed by Lucas Chollet and John Bowler)
Adjusted and improved various checks in colorspace calculations.
(Contributed by John Bowler)
Rearranged the write order of colorspace chunks for better conformance
with the PNG v3 draft specification.
(Contributed by John Bowler)
Raised the minimum required CMake version from 3.6 to 3.14.
Forked off a development branch for libpng version 1.8.
Version 1.6.46 [January 23, 2025]
Added support for the mDCV and cLLI chunks.
(Contributed by John Bowler)
Fixed a build issue affecting C89 compilers.
This was a regression introduced in libpng-1.6.45.
(Contributed by John Bowler)
Added makefile.c89, specifically for testing C89 compilers.
Cleaned up contrib/pngminus: corrected an old typo, removed an old
workaround, and updated the CMake file.
Version 1.6.47 [February 18, 2025]
Modified the behaviour of colorspace chunks in order to adhere
to the new precedence rules formulated in the latest draft of
the PNG Specification.
(Contributed by John Bowler)
Fixed a latent bug in `png_write_iCCP`.
This would have been a read-beyond-end-of-malloc vulnerability,
introduced early in the libpng-1.6.0 development, yet (fortunately!)
it was inaccessible before the above-mentioned modification of the
colorspace precedence rules, due to pre-existing colorspace checks.
(Reported by Bob Friesenhahn; fixed by John Bowler)
Version 1.6.48 [April 30, 2025]
Fixed the floating-point version of the mDCv setter `png_set_mDCv`.
(Reported by Mohit Bakshi; fixed by John Bowler)
Added #error directives to discourage the inclusion of private
libpng implementation header files in PNG-supporting applications.
Added the CMake build option `PNG_LIBCONF_HEADER`, to be used as an
alternative to `DFA_XTRA`.
Removed the Travis CI configuration files, with heartfelt thanks for
their generous support of our project over the past five years!
Version 1.6.49 [June 12, 2025]
Added SIMD-optimized code for the RISC-V Vector Extension (RVV).
(Contributed by Manfred Schlaegl, Dragos Tiselice and Filip Wasil)
Added various fixes and improvements to the build scripts and to
the sample code.
Version 1.6.50 [July 1, 2025]
Improved the detection of the RVV Extension on the RISC-V platform.
(Contributed by Filip Wasil)
Replaced inline ASM with C intrinsics in the RVV code.
(Contributed by Filip Wasil)
Fixed a decoder defect in which unknown chunks trailing IDAT, set
to go through the unknown chunk handler, incorrectly triggered
out-of-place IEND errors.
(Contributed by John Bowler)
Fixed the CMake file for cross-platform builds that require `libm`.
Version 1.6.51 [November 21, 2025]
Fixed CVE-2025-64505 (moderate severity):
Heap buffer overflow in `png_do_quantize` via malformed palette index.
(Reported by Samsung; analyzed by Fabio Gritti.)
Fixed CVE-2025-64506 (moderate severity):
Heap buffer over-read in `png_write_image_8bit` with 8-bit input and
`convert_to_8bit` enabled.
(Reported by Samsung and <weijinjinnihao@users.noreply.github.com>;
analyzed by Fabio Gritti.)
Fixed CVE-2025-64720 (high severity):
Buffer overflow in `png_image_read_composite` via incorrect palette
premultiplication.
(Reported by Samsung; analyzed by John Bowler.)
Fixed CVE-2025-65018 (high severity):
Heap buffer overflow in `png_combine_row` triggered via
`png_image_finish_read`.
(Reported by <yosiimich@users.noreply.github.com>.)
Fixed a memory leak in `png_set_quantize`.
(Reported by Samsung; analyzed by Fabio Gritti.)
Removed the experimental and incomplete ERROR_NUMBERS code.
(Contributed by Tobias Stoeckmann.)
Improved the RISC-V vector extension support; required RVV 1.0 or newer.
(Contributed by Filip Wasil.)
Added GitHub Actions workflows for automated testing.
Performed various refactorings and cleanups.
Version 1.6.52 [December 3, 2025]
Fixed CVE-2025-66293 (high severity):
Out-of-bounds read in `png_image_read_composite`.
(Reported by flyfish101 <flyfish101@users.noreply.github.com>.)
Fixed the Paeth filter handling in the RISC-V RVV implementation.
(Reported by Filip Wasil; fixed by Liang Junzhao.)
Improved the performance of the RISC-V RVV implementation.
(Contributed by Liang Junzhao.)
Added allocation failure fuzzing to oss-fuzz.
(Contributed by Philippe Antoine.)
Version 1.6.53 [December 5, 2025]
Fixed a build failure on RISC-V RVV caused by a misspelled intrinsic.
(Contributed by Alexander Smorkalov.)
Fixed a build failure with CMake 4.1 or newer, on Windows, when using
Visual C++ without MASM installed.
Version 1.6.54 [January 12, 2026]
Fixed CVE-2026-22695 (medium severity):
Heap buffer over-read in `png_image_read_direct_scaled`.
(Reported and fixed by Petr Simecek.)
Fixed CVE-2026-22801 (medium severity):
Integer truncation causing heap buffer over-read in `png_image_write_*`.
Implemented various improvements in oss-fuzz.
(Contributed by Philippe Antoine.)
Version 1.6.55 [February 9, 2026]
Fixed CVE-2026-25646 (high severity):
Heap buffer overflow in `png_set_quantize`.
(Reported and fixed by Joshua Inscoe.)
Resolved an oss-fuzz build issue involving nalloc.
(Contributed by Philippe Antoine.)
Version 1.6.56 [March 25, 2026]
Fixed CVE-2026-33416 (high severity):
Use-after-free via pointer aliasing in `png_set_tRNS` and `png_set_PLTE`.
(Reported by Halil Oktay and Ryo Shimada;
fixed by Halil Oktay and Cosmin Truta.)
Fixed CVE-2026-33636 (high severity):
Out-of-bounds read/write in the palette expansion on ARM Neon.
(Reported by Taegu Ha; fixed by Taegu Ha and Cosmin Truta.)
Fixed uninitialized reads beyond `num_trans` in `trans_alpha` buffers.
(Contributed by Halil Oktay.)
Fixed stale `info_ptr->palette` after in-place gamma and background
transforms.
Fixed wrong channel indices in `png_image_read_and_map` RGB_ALPHA path.
(Contributed by Yuelin Wang.)
Fixed wrong background color in colormap read.
(Contributed by Yuelin Wang.)
Fixed dead loop in sPLT write.
(Contributed by Yuelin Wang.)
Added missing null pointer checks in four public API functions.
(Contributed by Yuelin Wang.)
Validated shift bit depths in `png_set_shift` to prevent infinite loop.
(Contributed by Yuelin Wang.)
Avoided undefined behavior in library and tests.
Deprecated the hardly-ever-tested POINTER_INDEXING config option.
Added negative-stride test coverage for the simplified API.
Fixed memory leaks and API misuse in oss-fuzz.
(Contributed by Owen Sanzas.)
Implemented various fixes and improvements in oss-fuzz.
(Contributed by Bob Friesenhahn and Philippe Antoine.)
Performed various refactorings and cleanups.
Version 1.6.57 [April 8, 2026]
Fixed CVE-2026-34757 (medium severity):
Use-after-free in `png_set_PLTE`, `png_set_tRNS` and `png_set_hIST`
leading to corrupted chunk data and potential heap information disclosure.
Also hardened the append-style setters (`png_set_text`, `png_set_sPLT`,
`png_set_unknown_chunks`) against a theoretical variant of the same
aliasing pattern.
(Reported by Iv4n <Iv4n550@users.noreply.github.com>.)
Fixed integer overflow in rowbytes computation in read transforms.
(Contributed by Mohammad Seet.)
Version 1.6.58 [April 15, 2026]
Fixed a regression introduced in version 1.6.56 that caused `png_get_PLTE`
to return stale palette data after applying gamma and background transforms
in-place.
(Reported by ralfjunker <ralfjunker@users.noreply.github.com>.)
Send comments/corrections/commendations to png-mng-implement at lists.sf.net.
Subscription is required; visit
<https://lists.sourceforge.net/lists/listinfo/png-mng-implement>
to subscribe.
#endif
+467
View File
@@ -0,0 +1,467 @@
Installing libpng
Contents
I. Simple installation
II. Rebuilding the configure scripts
III. Using scripts/makefile*
IV. Using cmake
V. Directory structure
VI. Building with project files
VII. Building with makefiles
VIII. Configuring libpng for 16-bit platforms
IX. Configuring for DOS
X. Configuring for Medium Model
XI. Prepending a prefix to exported symbols
XII. Configuring for compiler xxx:
XIII. Removing unwanted object code
XIV. Enabling or disabling hardware optimizations
XV. Changes to the build and configuration of libpng in libpng-1.5.x
XVI. Setjmp/longjmp issues
XVII. Common linking failures
XVIII. Other sources of information about libpng
I. Simple installation
On Unix/Linux and similar systems, you can simply type
./configure [--prefix=/path]
make check
make install
and ignore the rest of this document. "/path" is the path to the directory
where you want to install the libpng "lib", "include", and "bin"
subdirectories.
If you downloaded a GIT clone, you will need to run ./autogen.sh before
running ./configure, to create "configure" and "Makefile.in" which are
not included in the GIT repository.
Note that "configure" is only included in the "*.tar" distributions and not
in the "*.zip" or "*.7z" distributions. If you downloaded one of those
distributions, see "Building with project files" or "Building with makefiles",
below.
II. Rebuilding the configure scripts
If configure does not work on your system, or if you have a need to
change configure.ac or Makefile.am, and you have a reasonably
up-to-date set of tools, running ./autogen.sh in a git clone before
running ./configure may fix the problem. To be really sure that you
aren't using any of the included pre-built scripts, especially if you
are building from a tar distribution instead of a git distribution,
do this:
./configure --enable-maintainer-mode
make maintainer-clean
./autogen.sh --maintainer --clean
./autogen.sh --maintainer
./configure [--prefix=/path] [other options]
make
make install
make check
III. Using scripts/makefile*
Instead, you can use one of the custom-built makefiles in the
"scripts" directory
cp scripts/pnglibconf.h.prebuilt pnglibconf.h
cp scripts/makefile.system makefile
make test
make install
The files that are presently available in the scripts directory
are listed and described in scripts/README.txt.
Or you can use one of the "projects" in the "projects" directory.
Before installing libpng, you must first install zlib, if it
is not already on your system. zlib can usually be found
wherever you got libpng; otherwise go to https://zlib.net/. You can
place zlib in the same directory as libpng or in another directory.
If your system already has a preinstalled zlib you will still need
to have access to the zlib.h and zconf.h include files that
correspond to the version of zlib that's installed.
If you wish to test with a particular zlib that is not first in the
standard library search path, put ZLIBLIB, ZLIBINC, CPPFLAGS, LDFLAGS,
and LD_LIBRARY_PATH in your environment before running "make test"
or "make distcheck":
ZLIBLIB=/path/to/lib export ZLIBLIB
ZLIBINC=/path/to/include export ZLIBINC
CPPFLAGS="-I$ZLIBINC" export CPPFLAGS
LDFLAGS="-L$ZLIBLIB" export LDFLAGS
LD_LIBRARY_PATH="$ZLIBLIB:$LD_LIBRARY_PATH" export LD_LIBRARY_PATH
If you are using one of the makefile scripts, put ZLIBLIB and ZLIBINC
in your environment and type
make ZLIBLIB=$ZLIBLIB ZLIBINC=$ZLIBINC test
IV. Using cmake
If you want to use "cmake" (see www.cmake.org), type
cmake . -DCMAKE_INSTALL_PREFIX=/path
make
make install
As when using the simple configure method described above, "/path" points to
the installation directory where you want to put the libpng "lib", "include",
and "bin" subdirectories.
V. Directory structure
You can rename the directories that you downloaded (they
might be called "libpng-x.y.z" or "libpngNN" and "zlib-1.2.8"
or "zlib128") so that you have directories called "zlib" and "libpng".
Your directory structure should look like this:
.. (the parent directory)
libpng (this directory)
INSTALL (this file)
README
*.h, *.c => libpng source files
CMakeLists.txt => "cmake" script
ci
ci_*.sh
configuration files:
configure.ac, configure, Makefile.am, Makefile.in,
autogen.sh, config.guess, ltmain.sh, missing, libpng.pc.in,
libpng-config.in, aclocal.m4, config.h.in, config.sub,
depcomp, install-sh, mkinstalldirs, test-pngtest.sh, etc.
contrib
arm-neon, conftest, examples, gregbook, libtests, pngminim,
pngminus, pngsuite, tools, visupng, riscv-rvv
projects
owatcom, visualc71, vstudio
scripts
makefile.*
*.def (module definition files)
etc.
pngtest.png
etc.
zlib
README, *.h, *.c, contrib, etc.
If the line endings in the files look funny, you may wish to get the other
distribution of libpng. It is available in both tar.gz (UNIX style line
endings) and zip (DOS style line endings) formats.
VI. Building with project files
If you are building libpng with Microsoft Visual Studio, you can enter
the directory projects\visualc71 or projects\vstudio and follow the
instructions in README.txt.
Otherwise, enter the zlib directory and follow the instructions in
zlib/README, then come back here and run "configure" or choose the
appropriate makefile in the scripts directory.
VII. Building with makefiles
Copy the file (or files) that you need from the
scripts directory into this directory, for example
UNIX example:
cp scripts/makefile.std Makefile
make
Windows example:
nmake -f scripts\makefile.vcwin32
Read the makefile to see if you need to change any source or
target directories to match your preferences.
Then read pnglibconf.dfa to see if you want to make any configuration
changes.
Then just run "make" which will create the libpng library in
this directory and "make test" which will run a quick test that reads
the "pngtest.png" file and writes a "pngout.png" file that should be
identical to it. Look for "9782 zero samples" in the output of the
test. For more confidence, you can run another test by typing
"pngtest pngnow.png" and looking for "289 zero samples" in the output.
Also, you can run "pngtest -m contrib/pngsuite/*.png" and compare
your output with the result shown in contrib/pngsuite/README.
Most of the makefiles used to allow you to run "make install" to put
the library in its final resting place, but that feature is no longer
supported. The only tested and supported manners to install libpng are
the conventional build and install procedures driven by the configure
script or by the CMake file.
VIII. Configuring for DOS and other 16-bit platforms
Officially, the support for 16-bit platforms has been removed.
For DOS users who only have access to the lower 640K, you will
have to limit zlib's memory usage via a png_set_compression_mem_level()
call. See zlib.h or zconf.h in the zlib library for more information.
You may be or may not be in luck if you target the "large" memory model,
but all the smaller models ("small", "compact" and "medium") are known
to be unworkable. For DOS users who have access beyond the lower 640K,
a "flat" 32-bit DOS model (such as DJGPP) is strongly recommended.
For DOS users who only have access to the lower 640K, you will have to
limit zlib's memory usage via a png_set_compression_mem_level() call.
You will also have to look into zconf.h to tell zlib (and thus libpng)
that it cannot allocate more than 64K at a time. Even if you can, the
memory won't be accessible. Therefore, you should limit zlib and libpng
to 64K by defining MAXSEG_64K.
IX. Prepending a prefix to exported symbols
Starting with libpng-1.6.0, you can configure libpng (when using the
"configure" script) to prefix all exported symbols by means of the
configuration option "--with-libpng-prefix=FOO_", where FOO_ can be any
string beginning with a letter and containing only uppercase
and lowercase letters, digits, and the underscore (i.e., a C language
identifier). This creates a set of macros in pnglibconf.h, so this is
transparent to applications; their function calls get transformed by
the macros to use the modified names.
X. Configuring for compiler xxx:
All includes for libpng are in pngconf.h. If you need to add, change
or delete an include, this is the place to do it.
The includes that are not needed outside libpng are placed in pngpriv.h,
which is only used by the routines inside libpng itself.
The files in libpng proper only include pngpriv.h and png.h, which
in turn includes pngconf.h and, as of libpng-1.5.0, pnglibconf.h.
As of libpng-1.5.0, pngpriv.h also includes three other private header
files, pngstruct.h, pnginfo.h, and pngdebug.h, which contain material
that previously appeared in the public headers.
XI. Removing unwanted object code
There are a bunch of #define's in pngconf.h that control what parts of
libpng are compiled. All the defines end in _SUPPORTED. If you are
never going to use a capability, you can change the #define to #undef
before recompiling libpng and save yourself code and data space, or
you can turn off individual capabilities with defines that begin with
"PNG_NO_".
In libpng-1.5.0 and later, the #define's are in pnglibconf.h instead.
You can also turn all of the transforms and ancillary chunk capabilities
off en masse with compiler directives that define
PNG_NO_READ[or WRITE]_TRANSFORMS, or PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS,
or all four, along with directives to turn on any of the capabilities that
you do want. The PNG_NO_READ[or WRITE]_TRANSFORMS directives disable the
extra transformations but still leave the library fully capable of reading
and writing PNG files with all known public chunks. Use of the
PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS directive produces a library
that is incapable of reading or writing ancillary chunks. If you are
not using the progressive reading capability, you can turn that off
with PNG_NO_PROGRESSIVE_READ (don't confuse this with the INTERLACING
capability, which you'll still have).
All the reading and writing specific code are in separate files, so the
linker should only grab the files it needs. However, if you want to
make sure, or if you are building a stand alone library, all the
reading files start with "pngr" and all the writing files start with "pngw".
The files that don't match either (like png.c, pngtrans.c, etc.)
are used for both reading and writing, and always need to be included.
The progressive reader is in pngpread.c
If you are creating or distributing a dynamically linked library (a .so
or DLL file), you should not remove or disable any parts of the library,
as this will cause applications linked with different versions of the
library to fail if they call functions not available in your library.
The size of the library itself should not be an issue, because only
those sections that are actually used will be loaded into memory.
XII. Enabling or disabling hardware optimizations
Certain hardware capabilities, such as the Intel SSE instructions,
are normally detected at run time. Enable them with configure options
such as one of
--enable-arm-neon=yes
--enable-mips-msa=yes
--enable-intel-sse=yes
--enable-powerpc-vsx=yes
--enable-riscv-rvv=yes
or enable them all at once with
--enable-hardware-optimizations=yes
or, if you are not using "configure", you can use one
or more of
CPPFLAGS += "-DPNG_ARM_NEON"
CPPFLAGS += "-DPNG_MIPS_MSA"
CPPFLAGS += "-DPNG_INTEL_SSE"
CPPFLAGS += "-DPNG_POWERPC_VSX"
CPPFLAGS += "-DPNG_RISCV_RVV"
See for example scripts/makefile.linux-opt
If you wish to avoid using them,
you can disable them via the configure option
--disable-hardware-optimizations
to disable them all, or
--enable-intel-sse=no
to disable a particular one,
or via compiler-command options such as
CPPFLAGS += "-DPNG_ARM_NEON_OPT=0, -DPNG_MIPS_MSA_OPT=0,
-DPNG_INTEL_SSE_OPT=0, -DPNG_POWERPC_VSX_OPT=0,
-DPNG_RISCV_RVV_OPT=0"
If you are using cmake, hardware optimizations are "on"
by default. To disable them, use
cmake . -DPNG_ARM_NEON=no -DPNG_INTEL_SSE=no \
-DPNG_MIPS_MSA=no -DPNG_POWERPC_VSX=no \
-DPNG_RISCV_RVV=no
or disable them all at once with
cmake . -DPNG_HARDWARE_OPTIMIZATIONS=no
XIII. Changes to the build and configuration of libpng in libpng-1.5.x
Details of internal changes to the library code can be found in the CHANGES
file and in the GIT repository logs. These will be of no concern to the vast
majority of library users or builders; however, the few who configure libpng
to a non-default feature set may need to change how this is done.
There should be no need for library builders to alter build scripts if
these use the distributed build support - configure or the makefiles -
however, users of the makefiles may care to update their build scripts
to build pnglibconf.h where the corresponding makefile does not do so.
Building libpng with a non-default configuration has changed completely.
The old method using pngusr.h should still work correctly even though the
way pngusr.h is used in the build has been changed; however, library
builders will probably want to examine the changes to take advantage of
new capabilities and to simplify their build system.
A. Specific changes to library configuration capabilities
The exact mechanism used to control attributes of API functions has
changed. A single set of operating system independent macro definitions
is used and operating system specific directives are defined in
pnglibconf.h
As part of this the mechanism used to choose procedure call standards on
those systems that allow a choice has been changed. At present this only
affects certain Microsoft (DOS, Windows) and IBM (OS/2) operating systems
running on Intel processors. As before, PNGAPI is defined where required
to control the exported API functions; however, two new macros, PNGCBAPI
and PNGCAPI, are used instead for callback functions (PNGCBAPI) and
(PNGCAPI) for functions that must match a C library prototype (currently
only png_longjmp_ptr, which must match the C longjmp function.) The new
approach is documented in pngconf.h
Despite these changes, libpng 1.5.0 only supports the native C function
calling standard on those platforms tested so far ("__cdecl" on Microsoft
Windows). This is because the support requirements for alternative
calling conventions seem to no longer exist. Developers who find it
necessary to set PNG_API_RULE to 1 should advise the mailing list
(png-mng-implement) of this and library builders who use Openwatcom and
therefore set PNG_API_RULE to 2 should also contact the mailing list.
B. Changes to the configuration mechanism
Prior to libpng-1.5.0 library builders who needed to configure libpng
had either to modify the exported pngconf.h header file to add system
specific configuration or had to write feature selection macros into
pngusr.h and cause this to be included into pngconf.h by defining
PNG_USER_CONFIG. The latter mechanism had the disadvantage that an
application built without PNG_USER_CONFIG defined would see the
unmodified, default, libpng API and thus would probably fail to link.
These mechanisms still work in the configure build and in any makefile
build that builds pnglibconf.h, although the feature selection macros
have changed somewhat as described above. In 1.5.0, however, pngusr.h is
processed only once, at the time the exported header file pnglibconf.h is
built. pngconf.h no longer includes pngusr.h; therefore, pngusr.h is ignored
after the build of pnglibconf.h and it is never included in an application
build.
The formerly used alternative of adding a list of feature macros to the
CPPFLAGS setting in the build also still works; however, the macros will be
copied to pnglibconf.h and this may produce macro redefinition warnings
when the individual C files are compiled.
All configuration now only works if pnglibconf.h is built from
scripts/pnglibconf.dfa. This requires the program awk. Brian Kernighan
(the original author of awk) maintains C source code of that awk and this
and all known later implementations (often called by subtly different
names - nawk and gawk for example) are adequate to build pnglibconf.h.
The Sun Microsystems (now Oracle) program 'awk' is an earlier version
and does not work; this may also apply to other systems that have a
functioning awk called 'nawk'.
Configuration options are now documented in scripts/pnglibconf.dfa. This
file also includes dependency information that ensures a configuration is
consistent; that is, if a feature is switched off, dependent features are
also switched off. As a recommended alternative to using feature macros in
pngusr.h a system builder may also define equivalent options in pngusr.dfa
(or, indeed, any file) and add that to the configuration by setting
DFA_XTRA to the file name. The makefiles in contrib/pngminim illustrate
how to do this, and also illustrate a case where pngusr.h is still required.
After you have built libpng, the definitions that were recorded in
pnglibconf.h are available to your application (pnglibconf.h is included
in png.h and gets installed alongside png.h and pngconf.h in your
$PREFIX/include directory). Do not edit pnglibconf.h after you have built
libpng, because than the settings would not accurately reflect the settings
that were used to build libpng.
XIV. Setjmp/longjmp issues
Libpng uses setjmp()/longjmp() for error handling. Unfortunately setjmp()
is known to be not thread-safe on some platforms and we don't know of
any platform where it is guaranteed to be thread-safe. Therefore, if
your application is going to be using multiple threads, you should
configure libpng with PNG_NO_SETJMP in your pngusr.dfa file, with
-DPNG_NO_SETJMP on your compile line, or with
#undef PNG_SETJMP_SUPPORTED
in your pnglibconf.h or pngusr.h.
Starting with libpng-1.6.0, the library included a "simplified API".
This requires setjmp/longjmp, so you must either build the library
with PNG_SETJMP_SUPPORTED defined, or with PNG_SIMPLIFIED_READ_SUPPORTED
and PNG_SIMPLIFIED_WRITE_SUPPORTED undefined.
XV. Common linking failures
If your application fails to find libpng or zlib entries while linking:
Be sure "-lz" appears after "-lpng" on your linking command.
Be sure you have built libpng, zlib, and your application for the
same platform (e.g., 32-bit or 64-bit).
If you are using the vstudio project, observe the WARNING in
project/vstudio/README.txt.
XVI. Other sources of information about libpng:
Further information can be found in the README and libpng-manual.txt
files, in the individual makefiles, in png.h, and the manual pages
libpng.3 and png.5.
Copyright (c) 2022 Cosmin Truta
Copyright (c) 1998-2002,2006-2016 Glenn Randers-Pehrson
This document is released under the libpng license.
For conditions of distribution and use, see the disclaimer
and license in png.h.
+100 -79
View File
@@ -1,4 +1,3 @@
This copy of the libpng notices is provided for your convenience. In case of
any discrepancy between this copy and the notices in the file png.h that is
included in the libpng distribution, the latter shall prevail.
@@ -24,43 +23,93 @@ Copyright (c) 2016 Google, Inc., and consist of the source files in the
"sse2" subdirectory and added code in pngpriv.h delimited by
#ifndef PNG_INTEL_SSE_OPT / #endif directives.
This modified version of libpng code adds animated PNG support and is
released under the libpng license described below. The modifications are
Copyright (c) 2006-2007 Andrew Smith, Copyright (c) 2008-2016 Max Stepin,
and are delimited by "#ifdef PNG_APNG_SUPPORTED / #endif" directives
surrounding them in the modified libpng source files.
This code is released under the libpng license.
libpng versions 1.0.7, July 1, 2000 through 1.6.26, Octoaber 20, 2016 are
Copyright (c) 2000-2002, 2004, 2006-2016 Glenn Randers-Pehrson, are
COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
=========================================
PNG Reference Library License version 2
---------------------------------------
* Copyright (c) 1995-2026 The PNG Reference Library Authors.
* Copyright (c) 2018-2026 Cosmin Truta.
* Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
* Copyright (c) 1996-1997 Andreas Dilger.
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
The software is supplied "as is", without warranty of any kind,
express or implied, including, without limitation, the warranties
of merchantability, fitness for a particular purpose, title, and
non-infringement. In no event shall the Copyright owners, or
anyone distributing the software, be liable for any damages or
other liability, whether in contract, tort or otherwise, arising
from, out of, or in connection with the software, or the use or
other dealings in the software, even if advised of the possibility
of such damage.
Permission is hereby granted to use, copy, modify, and distribute
this software, or portions hereof, for any purpose, without fee,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you
must not claim that you wrote the original software. If you
use this software in a product, an acknowledgment in the product
documentation would be appreciated, but is not required.
2. Altered source versions must be plainly marked as such, and must
not be misrepresented as being the original software.
3. This Copyright notice may not be removed or altered from any
source or altered source distribution.
PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35)
-----------------------------------------------------------------------
libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are
Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are
derived from libpng-1.0.6, and are distributed according to the same
disclaimer and license as libpng-1.0.6 with the following individuals
added to the list of Contributing Authors:
Simon-Pierre Cadieux
Eric S. Raymond
Mans Rullgard
Cosmin Truta
Gilles Vollant
James Yu
Simon-Pierre Cadieux
Eric S. Raymond
Mans Rullgard
Cosmin Truta
Gilles Vollant
James Yu
Mandar Sahastrabuddhe
Google Inc.
Vadim Barkov
and with the following additions to the disclaimer:
There is no warranty against interference with your enjoyment of the
library or against infringement. There is no warranty that our
efforts or the library will fulfill any of your particular purposes
or needs. This library is provided with all faults, and the entire
risk of satisfactory quality, performance, accuracy, and effort is with
the user.
There is no warranty against interference with your enjoyment of
the library or against infringement. There is no warranty that our
efforts or the library will fulfill any of your particular purposes
or needs. This library is provided with all faults, and the entire
risk of satisfactory quality, performance, accuracy, and effort is
with the user.
Some files in the "contrib" directory and some configure-generated
files that are distributed with libpng have other copyright owners and
files that are distributed with libpng have other copyright owners, and
are released under other open source licenses.
libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
libpng-0.96, and are distributed according to the same disclaimer and
license as libpng-0.96, with the following individuals added to the list
of Contributing Authors:
license as libpng-0.96, with the following individuals added to the
list of Contributing Authors:
Tom Lane
Glenn Randers-Pehrson
Willem van Schaik
Tom Lane
Glenn Randers-Pehrson
Willem van Schaik
libpng versions 0.89, June 1996, through 0.96, May 1997, are
Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
@@ -68,14 +117,14 @@ and are distributed according to the same disclaimer and license as
libpng-0.88, with the following individuals added to the list of
Contributing Authors:
John Bowler
Kevin Bracey
Sam Bushell
Magnus Holmgren
Greg Roelofs
Tom Tanner
John Bowler
Kevin Bracey
Sam Bushell
Magnus Holmgren
Greg Roelofs
Tom Tanner
Some files in the "scripts" directory have other copyright owners
Some files in the "scripts" directory have other copyright owners,
but are released under this license.
libpng versions 0.5, May 1995, through 0.88, January 1996, are
@@ -84,63 +133,35 @@ Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
For the purposes of this copyright and license, "Contributing Authors"
is defined as the following set of individuals:
Andreas Dilger
Dave Martindale
Guy Eric Schalnat
Paul Schmidt
Tim Wegner
Andreas Dilger
Dave Martindale
Guy Eric Schalnat
Paul Schmidt
Tim Wegner
The PNG Reference Library is supplied "AS IS". The Contributing Authors
and Group 42, Inc. disclaim all warranties, expressed or implied,
including, without limitation, the warranties of merchantability and of
fitness for any purpose. The Contributing Authors and Group 42, Inc.
assume no liability for direct, indirect, incidental, special, exemplary,
or consequential damages, which may result from the use of the PNG
Reference Library, even if advised of the possibility of such damage.
The PNG Reference Library is supplied "AS IS". The Contributing
Authors and Group 42, Inc. disclaim all warranties, expressed or
implied, including, without limitation, the warranties of
merchantability and of fitness for any purpose. The Contributing
Authors and Group 42, Inc. assume no liability for direct, indirect,
incidental, special, exemplary, or consequential damages, which may
result from the use of the PNG Reference Library, even if advised of
the possibility of such damage.
Permission is hereby granted to use, copy, modify, and distribute this
source code, or portions hereof, for any purpose, without fee, subject
to the following restrictions:
1. The origin of this source code must not be misrepresented.
1. The origin of this source code must not be misrepresented.
2. Altered versions must be plainly marked as such and must not
be misrepresented as being the original source.
2. Altered versions must be plainly marked as such and must not
be misrepresented as being the original source.
3. This Copyright notice may not be removed or altered from any
source or altered source distribution.
3. This Copyright notice may not be removed or altered from any
source or altered source distribution.
The Contributing Authors and Group 42, Inc. specifically permit, without
fee, and encourage the use of this source code as a component to
supporting the PNG file format in commercial products. If you use this
source code in a product, acknowledgment is not required but would be
appreciated.
END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE.
TRADEMARK:
The name "libpng" has not been registered by the Copyright owner
as a trademark in any jurisdiction. However, because libpng has
been distributed and maintained world-wide, continually since 1995,
the Copyright owner claims "common-law trademark protection" in any
jurisdiction where common-law trademark is recognized.
OSI CERTIFICATION:
Libpng is OSI Certified Open Source Software. OSI Certified Open Source is
a certification mark of the Open Source Initiative. OSI has not addressed
the additional disclaimers inserted at version 1.0.7.
EXPORT CONTROL:
The Copyright owner believes that the Export Control Classification
Number (ECCN) for libpng is EAR99, which means not subject to export
controls or International Traffic in Arms Regulations (ITAR) because
it is open source, publicly available software, that does not contain
any encryption software. See the EAR, paragraphs 734.3(b)(3) and
734.7(b).
Glenn Randers-Pehrson
glennrp at users.sourceforge.net
October 20, 2016
The Contributing Authors and Group 42, Inc. specifically permit,
without fee, and encourage the use of this source code as a component
to supporting the PNG file format in commercial products. If you use
this source code in a product, acknowledgment is not required but would
be appreciated.
-131
View File
@@ -1,131 +0,0 @@
Changes made to pristine libpng source by mozilla.org developers.
2016/10/20 -- Synced with libpng-1.6.26 (bug #1311776).
2016/09/01 -- Synced with libpng-1.6.25 (bug #1299590).
2016/08/11 -- Enabled SSE2 support (bug #1276127).
2016/08/06 -- Synced with libpng-1.6.24 (bug #1291986).
2016/06/09 -- Synced with libpng-1.6.23 (bug #1275901).
2016/01/16 -- Synced with libpng-1.6.21 (bug #1230757).
2015/11/12 -- Synced with libpng-1.6.19 (bug #1224244).
2015/07/30 -- Synced with libpng-1.6.18 (bug #1186977).
2015/03/27 -- Synced with libpng-1.6.17 (bug #1147909).
2014/12/22 -- Synced with libpng-1.6.16 (bug #1114360).
Added arm.patch file.
2014/11/20 -- Synced with libpng-1.6.15 (bug #1102523).
2014/10/23 -- Synced with libpng-1.6.14 (bug #1087841).
2014/08/21 -- Synced with libpng-1.6.13 (bug #1021713).
Renamed mozpngconf.h to pnglibconf.h.
Revised system arm/filter_neon.S to include the lines
#define PNG_READ_SUPPORTED and #define MOZ_PNG_HAVE_ARM_NEON
because the moz.build system doesn't yet pass -DDefined
macros to the assembler.
2014/03/21 -- Synced with libpng-1.6.10 (bug #980488) and disabled
PNG_WARNINGS and PNG_ERROR_TEXT in non-debug builds.
Limit image dimensions to 32767 (bug #251381, #591822,
and #967656).
2014/03/04 -- Enabled PNG_WARNINGS and other stuff in mozpngconf.h
as part of enabling Freetype2 with PNG (bug #969814).
2014/03/03 -- Fixed hang with empty IDAT (bug #974825). This will be
fixed in libpng-1.6.10.
2014/02/18 -- Exposed png_error(), etc. redefinitions to applications
(moved them from pngpriv.h to png.h). This will be fixed
in libpng-1.6.10.
2014/02/18 -- Disabled PNG_FIXED_POINT_SUPPORTED in mozpngconf.h (we
don't need both FIXED and FLOATING_POINT support).
2014/02/15 -- Synced with libpng-1.6.9 (bug #952505).
2014/02/11 -- Fixed crash with empty PLTE, CVE-2013-6954 (bug #945912).
This will be fixed in libpng-1.6.9.
2013/12/11 -- Enable ARM support (bug #832390).
2013/11/17 -- Synced with libpng-1.6.7 (bug #938740).
2013/09/21 -- Synced with libpng-1.6.6 (bug #841734).
2013/07/17 -- Synced with libpng-1.5.17 (bug #886499).
2013/06/06 -- Synced with libpng-1.5.16 (bug #873001).
2013/04/11 -- Synced with libpng-1.5.15 (bug #858578).
2013/01/24 -- Synced with libpng-1.5.14 (bug #832487).
2013/01/23 -- Disabled TEXT support in mozpngconf.h (bug #833594).
2012/10/02 -- Synced with libpng-1.5.13 (bug #775662).
2012/07/16 -- Add an "APNG-aware app" flag (bug #759067).
2012/07/04 -- Synced with libpng-1.5.11 (bug #771394).
2012/04/13 -- Synced with libpng-1.5.10 (bug #745178).
2012/02/19 -- Synced with libpng-1.5.9 (bug #648690).
2011/07/20 -- Synced with libpng-1.4.8 (bug #669863).
2011/04/08 -- Synced with libpng-1.4.7 (bug #624133).
2010/06/30 -- Synced with libpng-1.4.3 (bug #564792).
2010/02/26 -- Synced with libpng-1.4.1 (bug #544747).
2010/01/04 -- Synced with libpng-1.4.0 (bug #532645).
2009/09/10 -- Synced with libpng-1.2.40 (bug #492200 and #504805).
Moved location of acTL chunk to just after IHDR
in output PNG file.
2009/06/01 -- Eliminated incorrect test and rejection of APNG
blend_op in opaque images (bug #441971 and #455140).
2009/05/17 -- Always clear prev_row for each APNG frame (bug #463465).
2009/02/19 -- Synced with libpng-1.2.35 (bug #478901).
2008/08/21 -- Synced with libpng-1.2.31 (bug #418900).
2008/03/29 -- Initialize prev_row for each APNG frame, only when
the frame size increases (bug #420416).
2008/01/18 -- Synced with libpng-1.2.24 (bug #408429).
2007/11/13 -- Synced with libpng-1.2.23; Removed pnggccrd.c and pngvcrd.c;
Reduced footprint by removing error and warning text in
non-debug builds via settings in mozpngconf.h (bug #403239).
2007/11/06 -- Synced with libpng-1.2.22 (removes MMX support) (bug #386585).
2007/07/27 -- Enabled cHRM and iCCP chunks for color management (bug #16769).
2007/05/05 -- Zeroed png_ptr->num_trans on CRC error (bug #374810).
2007/04/19 -- Synced with libpng-1.2.16 tree (bug #373249).
2007/03/20 -- Added support for APNG (bug #257197).
2006/06/27 -- Synced with libpng-1.2.12 tree (bug #334110).
2004/10/07 -- Synced with libpng-1.2.7 tree (bug #261922).
2004/10/07 -- Added mozpngconf.h (bug #208607).
+156 -190
View File
@@ -1,56 +1,88 @@
README for libpng version 1.6.26 - October 20, 2016 (shared library 16.0)
See the note about version numbers near the top of png.h
README for libpng version 1.6.58
================================
See INSTALL for instructions on how to install libpng.
See the note about version numbers near the top of `png.h`.
See `INSTALL` for instructions on how to install libpng.
Libpng comes in several distribution formats. Get libpng-*.tar.gz or
libpng-*.tar.xz or if you want UNIX-style line endings in the text files,
or lpng*.7z or lpng*.zip if you want DOS-style line endings.
Libpng comes in several distribution formats. Get `libpng-*.tar.gz`
or `libpng-*.tar.xz` if you want UNIX-style line endings in the text
files, or `lpng*.7z` or `lpng*.zip` if you want DOS-style line endings.
Version 0.89 was the first official release of libpng. Don't let the
fact that it's the first release fool you. The libpng library has been in
extensive use and testing since mid-1995. By late 1997 it had
finally gotten to the stage where there hadn't been significant
changes to the API in some time, and people have a bad feeling about
libraries with versions < 1.0. Version 1.0.0 was released in
March 1998.
For a detailed description on using libpng, read `libpng-manual.txt`.
For examples of libpng in a program, see `example.c` and `pngtest.c`.
For usage information and restrictions (what little they are) on libpng,
see `png.h`. For a description on using zlib (the compression library
used by libpng) and zlib's restrictions, see `zlib.h`.
****
Note that some of the changes to the png_info structure render this
You should use zlib 1.0.4 or later to run this, but it _may_ work with
versions as old as zlib 0.95. Even so, there are bugs in older zlib
versions which can cause the output of invalid compression streams for
some images.
You should also note that zlib is a compression library that is useful
for more things than just PNG files. You can use zlib as a drop-in
replacement for `fread()` and `fwrite()`, if you are so inclined.
zlib should be available at the same place that libpng is, or at
<https://zlib.net>.
You may also want a copy of the PNG specification. It is available
as an RFC, a W3C Recommendation, and an ISO/IEC Standard. You can find
these at <http://www.libpng.org/pub/png/pngdocs.html>.
This code is currently being archived at <https://libpng.sourceforge.io>
in the download area, and at <http://libpng.download/src>.
This release, based in a large way on Glenn's, Guy's and Andreas'
earlier work, was created and will be supported by myself and the PNG
development group.
Send comments, corrections and commendations to `png-mng-implement`
at `lists.sourceforge.net`. (Subscription is required; visit
<https://lists.sourceforge.net/lists/listinfo/png-mng-implement>
to subscribe.)
Send general questions about the PNG specification to `png-mng-misc`
at `lists.sourceforge.net`. (Subscription is required; visit
<https://lists.sourceforge.net/lists/listinfo/png-mng-misc>
to subscribe.)
Historical notes
----------------
The libpng library has been in extensive use and testing since mid-1995.
Version 0.89, published a year later, was the first official release.
By late 1997, it had finally gotten to the stage where there hadn't
been significant changes to the API in some time, and people have a bad
feeling about libraries with versions below 1.0. Version 1.0.0 was
released in March 1998.
Note that some of the changes to the `png_info` structure render this
version of the library binary incompatible with libpng-0.89 or
earlier versions if you are using a shared library. The type of the
"filler" parameter for png_set_filler() has changed from png_byte to
png_uint_32, which will affect shared-library applications that use
this function.
`filler` parameter for `png_set_filler()` has changed from `png_byte`
to `png_uint_32`, which will affect shared-library applications that
use this function.
To avoid problems with changes to the internals of png info_struct,
To avoid problems with changes to the internals of the `info_struct`,
new APIs have been made available in 0.95 to avoid direct application
access to info_ptr. These functions are the png_set_<chunk> and
png_get_<chunk> functions. These functions should be used when
accessing/storing the info_struct data, rather than manipulating it
access to `info_ptr`. These functions are the `png_set_<chunk>` and
`png_get_<chunk>` functions. These functions should be used when
accessing/storing the `info_struct` data, rather than manipulating it
directly, to avoid such problems in the future.
It is important to note that the APIs did not make current programs
that access the info struct directly incompatible with the new
library, through libpng-1.2.x. In libpng-1.4.x, which was meant to
be a transitional release, members of the png_struct and the
info_struct can still be accessed, but the compiler will issue a
be a transitional release, members of the `png_struct` and the
`info_struct` can still be accessed, but the compiler will issue a
warning about deprecated usage. Since libpng-1.5.0, direct access
to these structs is not allowed, and the definitions of the structs
reside in private pngstruct.h and pnginfo.h header files that are not
accessible to applications. It is strongly suggested that new
programs use the new APIs (as shown in example.c and pngtest.c), and
older programs be converted to the new format, to facilitate upgrades
in the future.
****
Additions since 0.90 include the ability to compile libpng as a
Windows DLL, and new APIs for accessing data in the info struct.
Experimental functions include the ability to set weighting and cost
factors for row filter selection, direct reads of integers from buffers
on big-endian processors that support misaligned data access, faster
methods of doing alpha composition, and more accurate 16->8 bit color
conversion.
reside in private `pngstruct.h` and `pnginfo.h` header files that are
not accessible to applications. It is strongly suggested that new
programs use the new APIs (as shown in `example.c` and `pngtest.c`),
and older programs be converted to the new format, to facilitate
upgrades in the future.
The additions since 0.89 include the ability to read from a PNG stream
which has had some (or all) of the signature bytes read by the calling
@@ -60,159 +92,93 @@ the library action on the detection of chunk CRC errors. It is possible
to set different actions based on whether the CRC error occurred in a
critical or an ancillary chunk.
The changes made to the library, and bugs fixed are based on discussions
on the PNG-implement mailing list and not on material submitted
privately to Guy, Andreas, or Glenn. They will forward any good
suggestions to the list.
The additions since 0.90 include the ability to compile libpng as a
Windows DLL, and new APIs for accessing data in the `info_struct`.
Experimental functions included the ability to set weighting and cost
factors for row filter selection, direct reads of integers from buffers
on big-endian processors that support misaligned data access, faster
methods of doing alpha composition, and more accurate 16-to-8 bit color
conversion. Some of these experimental functions, such as the weighted
filter heuristics, have since been removed.
For a detailed description on using libpng, read libpng-manual.txt. For
examples of libpng in a program, see example.c and pngtest.c. For usage
information and restrictions (what little they are) on libpng, see
png.h. For a description on using zlib (the compression library used by
libpng) and zlib's restrictions, see zlib.h
Files included in this distribution
-----------------------------------
I have included a general makefile, as well as several machine and
compiler specific ones, but you may have to modify one for your own needs.
ANNOUNCE => Announcement of this version, with recent changes
AUTHORS => List of contributing authors
CHANGES => Description of changes between libpng versions
INSTALL => Instructions to install libpng
LICENSE => License to use and redistribute libpng
README => This file
TODO => Things not implemented in the current library
TRADEMARK => Trademark information
example.c => Example code for using libpng functions
libpng.3 => Manual page for libpng (includes libpng-manual.txt)
libpng-manual.txt => Description of libpng and its functions
libpngpf.3 => Manual page for libpng's private functions (deprecated)
png.5 => Manual page for the PNG format
png.c => Basic interface functions common to library
png.h => Library function and interface declarations (public)
pngpriv.h => Library function and interface declarations (private)
pngconf.h => System specific library configuration (public)
pngstruct.h => png_struct declaration (private)
pnginfo.h => png_info struct declaration (private)
pngdebug.h => debugging macros (private)
pngerror.c => Error/warning message I/O functions
pngget.c => Functions for retrieving info from struct
pngmem.c => Memory handling functions
pngbar.png => PNG logo, 88x31
pngnow.png => PNG logo, 98x31
pngpread.c => Progressive reading functions
pngread.c => Read data/helper high-level functions
pngrio.c => Lowest-level data read I/O functions
pngrtran.c => Read data transformation functions
pngrutil.c => Read data utility functions
pngset.c => Functions for storing data into the info_struct
pngtest.c => Library test program
pngtest.png => Library test sample image
pngtrans.c => Common data transformation functions
pngwio.c => Lowest-level write I/O functions
pngwrite.c => High-level write functions
pngwtran.c => Write data transformations
pngwutil.c => Write utility functions
arm/ => Optimized code for ARM Neon
intel/ => Optimized code for INTEL SSE2
loongarch/ => Optimized code for LoongArch LSX
mips/ => Optimized code for MIPS MSA and MIPS MMI
powerpc/ => Optimized code for PowerPC VSX
riscv/ => Optimized code for the RISC-V platform
ci/ => Scripts for continuous integration
contrib/ => External contributions
arm-neon/ => Optimized code for the ARM-NEON platform
mips-msa/ => Optimized code for the MIPS-MSA platform
powerpc-vsx/ => Optimized code for the POWERPC-VSX platform
examples/ => Examples of libpng usage
gregbook/ => Source code for PNG reading and writing, from
"PNG: The Definitive Guide" by Greg Roelofs,
O'Reilly, 1999
libtests/ => Test programs
pngexif/ => Program to inspect the EXIF information in PNG files
pngminim/ => Minimal decoder, encoder, and progressive decoder
programs demonstrating the use of pngusr.dfa
pngminus/ => Simple pnm2png and png2pnm programs
pngsuite/ => Test images
riscv-rvv/ => Optimized code for the RISC-V Vector platform
testpngs/ => Test images
tools/ => Various tools
visupng/ => VisualPng, a Windows viewer for PNG images
projects/ => Project files and workspaces for various IDEs
owatcom/ => OpenWatcom project
visualc71/ => Microsoft Visual C++ 7.1 workspace
vstudio/ => Microsoft Visual Studio workspace
scripts/ => Scripts and makefiles for building libpng
(see scripts/README.txt for the complete list)
tests/ => Test scripts
You should use zlib 1.0.4 or later to run this, but it MAY work with
versions as old as zlib 0.95. Even so, there are bugs in older zlib
versions which can cause the output of invalid compression streams for
some images. You will definitely need zlib 1.0.4 or later if you are
taking advantage of the MS-DOS "far" structure allocation for the small
and medium memory models. You should also note that zlib is a
compression library that is useful for more things than just PNG files.
You can use zlib as a drop-in replacement for fread() and fwrite() if
you are so inclined.
Good luck, and happy coding!
zlib should be available at the same place that libpng is, or at zlib.net.
You may also want a copy of the PNG specification. It is available
as an RFC, a W3C Recommendation, and an ISO/IEC Standard. You can find
these at http://www.libpng.org/pub/png/documents/
This code is currently being archived at libpng.sf.net in the
[DOWNLOAD] area, and at ftp://ftp.simplesystems.org. If you can't find it
in any of those places, e-mail me, and I'll help you find it.
I am not a lawyer, but I believe that the Export Control Classification
Number (ECCN) for libpng is EAR99, which means not subject to export
controls or International Traffic in Arms Regulations (ITAR) because it
is open source, publicly available software, that does not contain any
encryption software. See the EAR, paragraphs 734.3(b)(3) and 734.7(b).
If you have any code changes, requests, problems, etc., please e-mail
them to me. Also, I'd appreciate any make files or project files,
and any modifications you needed to make to get libpng to compile,
along with a #define variable to tell what compiler/system you are on.
If you needed to add transformations to libpng, or wish libpng would
provide the image in a different way, drop me a note (and code, if
possible), so I can consider supporting the transformation.
Finally, if you get any warning messages when compiling libpng
(note: not zlib), and they are easy to fix, I'd appreciate the
fix. Please mention "libpng" somewhere in the subject line. Thanks.
This release was created and will be supported by myself (of course
based in a large way on Guy's and Andreas' earlier work), and the PNG
development group.
Send comments/corrections/commendations to png-mng-implement at
lists.sourceforge.net (subscription required; visit
https://lists.sourceforge.net/lists/listinfo/png-mng-implement
to subscribe) or to glennrp at users.sourceforge.net
You can't reach Guy, the original libpng author, at the addresses
given in previous versions of this document. He and Andreas will
read mail addressed to the png-implement list, however.
Please do not send general questions about PNG. Send them to
png-mng-misc at lists.sf.net (subscription required; visit
https://lists.sourceforge.net/lists/listinfo/png-mng-misc to
subscribe). If you have a question about something
in the PNG specification that is related to using libpng, send it
to me. Send me any questions that start with "I was using libpng,
and ...". If in doubt, send questions to me. I'll bounce them
to others, if necessary.
Please do not send suggestions on how to change PNG. We have
been discussing PNG for twenty years now, and it is official and
finished. If you have suggestions for libpng, however, I'll
gladly listen. Even if your suggestion is not used immediately,
it may be used later.
Files in this distribution:
ANNOUNCE => Announcement of this version, with recent changes
CHANGES => Description of changes between libpng versions
KNOWNBUG => List of known bugs and deficiencies
LICENSE => License to use and redistribute libpng
README => This file
TODO => Things not implemented in the current library
Y2KINFO => Statement of Y2K compliance
example.c => Example code for using libpng functions
libpng.3 => manual page for libpng (includes libpng-manual.txt)
libpng-manual.txt => Description of libpng and its functions
libpngpf.3 => manual page for libpng's private functions
png.5 => manual page for the PNG format
png.c => Basic interface functions common to library
png.h => Library function and interface declarations (public)
pngpriv.h => Library function and interface declarations (private)
pngconf.h => System specific library configuration (public)
pngstruct.h => png_struct declaration (private)
pnginfo.h => png_info struct declaration (private)
pngdebug.h => debugging macros (private)
pngerror.c => Error/warning message I/O functions
pngget.c => Functions for retrieving info from struct
pngmem.c => Memory handling functions
pngbar.png => PNG logo, 88x31
pngnow.png => PNG logo, 98x31
pngpread.c => Progressive reading functions
pngread.c => Read data/helper high-level functions
pngrio.c => Lowest-level data read I/O functions
pngrtran.c => Read data transformation functions
pngrutil.c => Read data utility functions
pngset.c => Functions for storing data into the info_struct
pngtest.c => Library test program
pngtest.png => Library test sample image
pngtrans.c => Common data transformation functions
pngwio.c => Lowest-level write I/O functions
pngwrite.c => High-level write functions
pngwtran.c => Write data transformations
pngwutil.c => Write utility functions
arm => Contains optimized code for the ARM platform
contrib => Contributions
arm-neon => Optimized code for ARM-NEON platform
examples => Example programs
gregbook => source code for PNG reading and writing, from
Greg Roelofs' "PNG: The Definitive Guide",
O'Reilly, 1999
intel => Optimized code for INTEL-SSE2 platform
libtests => Test programs
pngminim => Minimal decoder, encoder, and progressive decoder
programs demonstrating use of pngusr.dfa
pngminus => Simple pnm2png and png2pnm programs
pngsuite => Test images
testpngs
tools => Various tools
visupng => Contains a MSVC workspace for VisualPng
projects => Contains project files and workspaces for
building a DLL
owatcom => Contains a WATCOM project for building libpng
visualc71 => Contains a Microsoft Visual C++ (MSVC)
workspace for building libpng and zlib
vstudio => Contains a Microsoft Visual C++ (MSVC)
workspace for building libpng and zlib
scripts => Directory containing scripts for building libpng:
(see scripts/README.txt for the list of scripts)
Good luck, and happy coding.
-Glenn Randers-Pehrson (current maintainer, since 1998)
Internet: glennrp at users.sourceforge.net
-Andreas Eric Dilger (former maintainer, 1996-1997)
Internet: adilger at enel.ucalgary.ca
Web: http://www-mddsp.enel.ucalgary.ca/People/adilger/
-Guy Eric Schalnat (original author and former maintainer, 1995-1996)
(formerly of Group 42, Inc)
Internet: gschal at infinet.com
* Cosmin Truta (current maintainer, since 2018)
* Glenn Randers-Pehrson (former maintainer, 1998-2018)
* Andreas Eric Dilger (former maintainer, 1996-1997)
* Guy Eric Schalnat (original author and former maintainer, 1995-1996)
(formerly of Group 42, Inc.)
+11
View File
@@ -0,0 +1,11 @@
This version of libpng has been patched to add APNG support.
libpng will (eventually) support this natively, as a departure from
the developers' initial stance on animation support, but the intended
release publication (using very similar code to our patches) is not
yet ready.
Once libpng 2.0.x (originally 1.8.x) is ready, our client-side patches
can likely be discarded and we can lean on upstream's direct support
from that point forward.
The apng.patch and arm.patch files are primarily for reference/as a
starting point for any libpng updates in the meantime.
+8
View File
@@ -0,0 +1,8 @@
TRADEMARK
=========
The name "libpng" has not been registered by the Copyright owners
as a trademark in any jurisdiction. However, because libpng has
been distributed and maintained world-wide, continually since 1995,
the Copyright owners claim "common-law trademark protection" in any
jurisdiction where common-law trademark is recognized.
+1091 -721
View File
File diff suppressed because it is too large. Load diff
+19 -16
View File
@@ -1,17 +1,15 @@
/* arm_init.c - NEON optimised filter functions
*
* Copyright (c) 2018-2022 Cosmin Truta
* Copyright (c) 2014,2016 Glenn Randers-Pehrson
* Written by Mans Rullgard, 2011.
* Last changed in libpng 1.6.22 [May 26, 2016]
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
/* Below, after checking __linux__, various non-C90 POSIX 1003.1 functions are
* called.
*/
/* This module requires POSIX 1003.1 functions. */
#define _POSIX_SOURCE 1
#include "../pngpriv.h"
@@ -32,25 +30,30 @@
* has partial support is contrib/arm-neon/linux.c - a generic Linux
* implementation which reads /proc/cpufino.
*/
#include <signal.h> /* for sig_atomic_t */
#ifndef PNG_ARM_NEON_FILE
# ifdef __linux__
# define PNG_ARM_NEON_FILE "linux.c"
# if defined(__aarch64__) || defined(_M_ARM64)
/* ARM Neon is expected to be unconditionally available on ARM64. */
# error PNG_ARM_NEON_CHECK_SUPPORTED must not be defined on ARM64
# elif defined(__ARM_NEON__) || defined(__ARM_NEON)
/* ARM Neon is expected to be available on the target CPU architecture. */
# error PNG_ARM_NEON_CHECK_SUPPORTED must not be defined on this CPU arch
# elif defined(__linux__)
# define PNG_ARM_NEON_FILE "linux.c"
# else
# error No support for run-time ARM Neon checking; use compile-time options
# endif
#endif
#ifdef PNG_ARM_NEON_FILE
#include <signal.h> /* for sig_atomic_t */
static int png_have_neon(png_structp png_ptr);
#include PNG_ARM_NEON_FILE
#else /* PNG_ARM_NEON_FILE */
# error "PNG_ARM_NEON_FILE undefined: no support for run-time ARM NEON checks"
#endif /* PNG_ARM_NEON_FILE */
#ifdef PNG_ARM_NEON_FILE
# include PNG_ARM_NEON_FILE
#endif
#endif /* PNG_ARM_NEON_CHECK_SUPPORTED */
#ifndef PNG_ALIGNED_MEMORY_SUPPORTED
# error "ALIGNED_MEMORY is required; set: -DPNG_ALIGNED_MEMORY_SUPPORTED"
# error ALIGNED_MEMORY is required; please define PNG_ALIGNED_MEMORY_SUPPORTED
#endif
void
+35 -234
View File
@@ -1,20 +1,30 @@
/* filter_neon.S - NEON optimised filter functions
/* filter_neon.S - placeholder file
*
* Copyright (c) 2014 Glenn Randers-Pehrson
* Written by Mans Rullgard, 2011.
* Last changed in libpng 1.6.16 [December 22, 2014]
* Copyright (c) 2024 Cosmin Truta
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
/* These are required because Mozilla's moz.build system doesn't pass
* -DDefined macros to the assembler.
/* IMPORTANT NOTE:
*
* Historically, the hand-coded assembler implementation of Neon optimizations
* in this module had not been in sync with the intrinsics-based implementation
* in filter_neon_intrinsics.c and palette_neon_intrinsics.c, at least since
* the introduction of riffled palette optimizations. Moreover, the assembler
* code used to work on 32-bit ARM only, and it caused problems, even if empty,
* on 64-bit ARM.
*
* All references to this module from our internal build scripts and projects
* have been removed.
*
* For the external projects that might still expect this module to be present,
* we leave this stub in place, for the remaining lifetime of libpng-1.6.x.
* Everything should continue to function normally, as long as there are no
* deliberate attempts to use the old hand-made assembler code. A build error
* will be raised otherwise.
*/
#define PNG_READ_SUPPORTED
#define MOZ_PNG_HAVE_ARM_NEON
/* This is required to get the symbol renames, which are #defines, and the
* definitions (or not) of PNG_ARM_NEON_OPT and PNG_ARM_NEON_IMPLEMENTATION.
@@ -22,238 +32,29 @@
#define PNG_VERSION_INFO_ONLY
#include "../pngpriv.h"
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits /* mark stack as non-executable */
#endif
#ifdef PNG_READ_SUPPORTED
/* Assembler NEON support - only works for 32-bit ARM (i.e. it does not work for
* ARM64). The code in arm/filter_neon_intrinsics.c supports ARM64, however it
* only works if -mfpu=neon is specified on the GCC command line. See pngpriv.h
* for the logic which sets PNG_USE_ARM_NEON_ASM:
*/
#if PNG_ARM_NEON_IMPLEMENTATION == 2 /* hand-coded assembler */
#if PNG_ARM_NEON_OPT > 0
#ifdef __ELF__
# define ELF
#if defined(__clang__)
#define GNUC_VERSION 0 /* not gcc, although it might pretend to be */
#elif defined(__GNUC__)
#define GNUC_MAJOR (__GNUC__ + 0)
#define GNUC_MINOR (__GNUC_MINOR__ + 0)
#define GNUC_PATCHLEVEL (__GNUC_PATCHLEVEL__ + 0)
#define GNUC_VERSION (GNUC_MAJOR * 10000 + GNUC_MINOR * 100 + GNUC_PATCHLEVEL)
#else
# define ELF @
#define GNUC_VERSION 0 /* not gcc */
#endif
.arch armv7-a
.fpu neon
#if (GNUC_VERSION > 0) && (GNUC_VERSION < 40300)
#error "PNG_ARM_NEON is not supported with gcc versions earlier than 4.3.0"
#elif GNUC_VERSION == 40504
#error "PNG_ARM_NEON is not supported with gcc version 4.5.4"
#else
#error "Please use 'arm/*_neon_intrinsics.c' for PNG_ARM_NEON support"
#endif
.macro func name, export=0
.macro endfunc
ELF .size \name, . - \name
.endfunc
.purgem endfunc
.endm
.text
/* Explicitly specifying alignment here because some versions of
* GAS don't align code correctly. This is harmless in correctly
* written versions of GAS.
*/
.align 2
.if \export
.global \name
.endif
ELF .type \name, STT_FUNC
.func \name
\name:
.endm
func png_read_filter_row_sub4_neon, export=1
ldr r3, [r0, #4] @ rowbytes
vmov.i8 d3, #0
1:
vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128]
vadd.u8 d0, d3, d4
vadd.u8 d1, d0, d5
vadd.u8 d2, d1, d6
vadd.u8 d3, d2, d7
vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
subs r3, r3, #16
bgt 1b
bx lr
endfunc
func png_read_filter_row_sub3_neon, export=1
ldr r3, [r0, #4] @ rowbytes
vmov.i8 d3, #0
mov r0, r1
mov r2, #3
mov r12, #12
vld1.8 {q11}, [r0], r12
1:
vext.8 d5, d22, d23, #3
vadd.u8 d0, d3, d22
vext.8 d6, d22, d23, #6
vadd.u8 d1, d0, d5
vext.8 d7, d23, d23, #1
vld1.8 {q11}, [r0], r12
vst1.32 {d0[0]}, [r1,:32], r2
vadd.u8 d2, d1, d6
vst1.32 {d1[0]}, [r1], r2
vadd.u8 d3, d2, d7
vst1.32 {d2[0]}, [r1], r2
vst1.32 {d3[0]}, [r1], r2
subs r3, r3, #12
bgt 1b
bx lr
endfunc
func png_read_filter_row_up_neon, export=1
ldr r3, [r0, #4] @ rowbytes
1:
vld1.8 {q0}, [r1,:128]
vld1.8 {q1}, [r2,:128]!
vadd.u8 q0, q0, q1
vst1.8 {q0}, [r1,:128]!
subs r3, r3, #16
bgt 1b
bx lr
endfunc
func png_read_filter_row_avg4_neon, export=1
ldr r12, [r0, #4] @ rowbytes
vmov.i8 d3, #0
1:
vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128]
vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]!
vhadd.u8 d0, d3, d16
vadd.u8 d0, d0, d4
vhadd.u8 d1, d0, d17
vadd.u8 d1, d1, d5
vhadd.u8 d2, d1, d18
vadd.u8 d2, d2, d6
vhadd.u8 d3, d2, d19
vadd.u8 d3, d3, d7
vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
subs r12, r12, #16
bgt 1b
bx lr
endfunc
func png_read_filter_row_avg3_neon, export=1
push {r4,lr}
ldr r12, [r0, #4] @ rowbytes
vmov.i8 d3, #0
mov r0, r1
mov r4, #3
mov lr, #12
vld1.8 {q11}, [r0], lr
1:
vld1.8 {q10}, [r2], lr
vext.8 d5, d22, d23, #3
vhadd.u8 d0, d3, d20
vext.8 d17, d20, d21, #3
vadd.u8 d0, d0, d22
vext.8 d6, d22, d23, #6
vhadd.u8 d1, d0, d17
vext.8 d18, d20, d21, #6
vadd.u8 d1, d1, d5
vext.8 d7, d23, d23, #1
vld1.8 {q11}, [r0], lr
vst1.32 {d0[0]}, [r1,:32], r4
vhadd.u8 d2, d1, d18
vst1.32 {d1[0]}, [r1], r4
vext.8 d19, d21, d21, #1
vadd.u8 d2, d2, d6
vhadd.u8 d3, d2, d19
vst1.32 {d2[0]}, [r1], r4
vadd.u8 d3, d3, d7
vst1.32 {d3[0]}, [r1], r4
subs r12, r12, #12
bgt 1b
pop {r4,pc}
endfunc
.macro paeth rx, ra, rb, rc
vaddl.u8 q12, \ra, \rb @ a + b
vaddl.u8 q15, \rc, \rc @ 2*c
vabdl.u8 q13, \rb, \rc @ pa
vabdl.u8 q14, \ra, \rc @ pb
vabd.u16 q15, q12, q15 @ pc
vcle.u16 q12, q13, q14 @ pa <= pb
vcle.u16 q13, q13, q15 @ pa <= pc
vcle.u16 q14, q14, q15 @ pb <= pc
vand q12, q12, q13 @ pa <= pb && pa <= pc
vmovn.u16 d28, q14
vmovn.u16 \rx, q12
vbsl d28, \rb, \rc
vbsl \rx, \ra, d28
.endm
func png_read_filter_row_paeth4_neon, export=1
ldr r12, [r0, #4] @ rowbytes
vmov.i8 d3, #0
vmov.i8 d20, #0
1:
vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128]
vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]!
paeth d0, d3, d16, d20
vadd.u8 d0, d0, d4
paeth d1, d0, d17, d16
vadd.u8 d1, d1, d5
paeth d2, d1, d18, d17
vadd.u8 d2, d2, d6
paeth d3, d2, d19, d18
vmov d20, d19
vadd.u8 d3, d3, d7
vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
subs r12, r12, #16
bgt 1b
bx lr
endfunc
func png_read_filter_row_paeth3_neon, export=1
push {r4,lr}
ldr r12, [r0, #4] @ rowbytes
vmov.i8 d3, #0
vmov.i8 d4, #0
mov r0, r1
mov r4, #3
mov lr, #12
vld1.8 {q11}, [r0], lr
1:
vld1.8 {q10}, [r2], lr
paeth d0, d3, d20, d4
vext.8 d5, d22, d23, #3
vadd.u8 d0, d0, d22
vext.8 d17, d20, d21, #3
paeth d1, d0, d17, d20
vst1.32 {d0[0]}, [r1,:32], r4
vext.8 d6, d22, d23, #6
vadd.u8 d1, d1, d5
vext.8 d18, d20, d21, #6
paeth d2, d1, d18, d17
vext.8 d7, d23, d23, #1
vld1.8 {q11}, [r0], lr
vst1.32 {d1[0]}, [r1], r4
vadd.u8 d2, d2, d6
vext.8 d19, d21, d21, #1
paeth d3, d2, d19, d18
vst1.32 {d2[0]}, [r1], r4
vmov d4, d19
vadd.u8 d3, d3, d7
vst1.32 {d3[0]}, [r1], r4
subs r12, r12, #12
bgt 1b
pop {r4,pc}
endfunc
#endif /* PNG_ARM_NEON_OPT > 0 */
#endif /* PNG_ARM_NEON_IMPLEMENTATION == 2 (assembler) */
#endif /* PNG_ARM_NEON_IMPLEMENTATION == 2 */
#endif /* READ */
+28 -14
View File
@@ -1,12 +1,10 @@
/* filter_neon_intrinsics.c - NEON optimised filter functions
*
* Copyright (c) 2018 Cosmin Truta
* Copyright (c) 2014,2016 Glenn Randers-Pehrson
* Written by James Yu <james.yu at linaro.org>, October 2013.
* Based on filter_neon.S, written by Mans Rullgard, 2011.
*
* Last changed in libpng 1.6.22 [May 26, 2016]
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
@@ -19,7 +17,11 @@
/* This code requires -mfpu=neon on the command line: */
#if PNG_ARM_NEON_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */
#include <arm_neon.h>
#if defined(_MSC_VER) && !defined(__clang__) && defined(_M_ARM64)
# include <arm64_neon.h>
#else
# include <arm_neon.h>
#endif
/* libpng row pointers are not necessarily aligned to any particular boundary,
* however this code will only work with appropriate alignment. arm/arm_init.c
@@ -33,6 +35,11 @@
* 'type'. This is written this way just to hide the GCC strict aliasing
* warning; note that the code is safe because there never is an alias between
* the input and output pointers.
*
* When compiling with MSVC ARM64, the png_ldr macro can't be passed directly
* to vst4_lane_u32, because of an internal compiler error inside MSVC.
* To avoid this compiler bug, we use a temporary variable (vdest_val) to store
* the result of png_ldr.
*/
#define png_ldr(type,pointer)\
(temp_pointer = png_ptr(type,pointer), *temp_pointer)
@@ -41,7 +48,7 @@
void
png_read_filter_row_up_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
png_const_bytep prev_row)
{
png_bytep rp = row;
png_bytep rp_stop = row + row_info->rowbytes;
@@ -62,7 +69,7 @@ png_read_filter_row_up_neon(png_row_infop row_info, png_bytep row,
void
png_read_filter_row_sub3_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
png_const_bytep prev_row)
{
png_bytep rp = row;
png_bytep rp_stop = row + row_info->rowbytes;
@@ -109,7 +116,7 @@ png_read_filter_row_sub3_neon(png_row_infop row_info, png_bytep row,
void
png_read_filter_row_sub4_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
png_const_bytep prev_row)
{
png_bytep rp = row;
png_bytep rp_stop = row + row_info->rowbytes;
@@ -125,12 +132,15 @@ png_read_filter_row_sub4_neon(png_row_infop row_info, png_bytep row,
uint8x8x4_t *vrpt = png_ptr(uint8x8x4_t,&vtmp);
uint8x8x4_t vrp = *vrpt;
uint32x2x4_t *temp_pointer;
uint32x2x4_t vdest_val;
vdest.val[0] = vadd_u8(vdest.val[3], vrp.val[0]);
vdest.val[1] = vadd_u8(vdest.val[0], vrp.val[1]);
vdest.val[2] = vadd_u8(vdest.val[1], vrp.val[2]);
vdest.val[3] = vadd_u8(vdest.val[2], vrp.val[3]);
vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0);
vdest_val = png_ldr(uint32x2x4_t, &vdest);
vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0);
}
PNG_UNUSED(prev_row)
@@ -138,7 +148,7 @@ png_read_filter_row_sub4_neon(png_row_infop row_info, png_bytep row,
void
png_read_filter_row_avg3_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
png_const_bytep prev_row)
{
png_bytep rp = row;
png_const_bytep pp = prev_row;
@@ -206,7 +216,7 @@ png_read_filter_row_avg3_neon(png_row_infop row_info, png_bytep row,
void
png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
png_const_bytep prev_row)
{
png_bytep rp = row;
png_bytep rp_stop = row + row_info->rowbytes;
@@ -223,6 +233,7 @@ png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep row,
uint8x8x4_t *vrpt, *vppt;
uint8x8x4_t vrp, vpp;
uint32x2x4_t *temp_pointer;
uint32x2x4_t vdest_val;
vtmp = vld4_u32(png_ptr(uint32_t,rp));
vrpt = png_ptr(uint8x8x4_t,&vtmp);
@@ -240,7 +251,8 @@ png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep row,
vdest.val[3] = vhadd_u8(vdest.val[2], vpp.val[3]);
vdest.val[3] = vadd_u8(vdest.val[3], vrp.val[3]);
vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0);
vdest_val = png_ldr(uint32x2x4_t, &vdest);
vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0);
}
}
@@ -273,7 +285,7 @@ paeth(uint8x8_t a, uint8x8_t b, uint8x8_t c)
void
png_read_filter_row_paeth3_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
png_const_bytep prev_row)
{
png_bytep rp = row;
png_const_bytep pp = prev_row;
@@ -341,7 +353,7 @@ png_read_filter_row_paeth3_neon(png_row_infop row_info, png_bytep row,
void
png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
png_const_bytep prev_row)
{
png_bytep rp = row;
png_bytep rp_stop = row + row_info->rowbytes;
@@ -359,6 +371,7 @@ png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row,
uint8x8x4_t *vrpt, *vppt;
uint8x8x4_t vrp, vpp;
uint32x2x4_t *temp_pointer;
uint32x2x4_t vdest_val;
vtmp = vld4_u32(png_ptr(uint32_t,rp));
vrpt = png_ptr(uint8x8x4_t,&vtmp);
@@ -378,7 +391,8 @@ png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row,
vlast = vpp.val[3];
vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0);
vdest_val = png_ldr(uint32x2x4_t, &vdest);
vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0);
}
}
+147
View File
@@ -0,0 +1,147 @@
/* palette_neon_intrinsics.c - NEON optimised palette expansion functions
*
* Copyright (c) 2018-2026 Cosmin Truta
* Copyright (c) 2017-2018 Arm Holdings. All rights reserved.
* Written by Richard Townsend <Richard.Townsend@arm.com>, February 2017.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
#include "../pngpriv.h"
#if PNG_ARM_NEON_IMPLEMENTATION == 1
#if defined(_MSC_VER) && !defined(__clang__) && defined(_M_ARM64)
# include <arm64_neon.h>
#else
# include <arm_neon.h>
#endif
/* Build an RGBA8 palette from the separate RGB and alpha palettes. */
void
png_riffle_palette_neon(png_structrp png_ptr)
{
png_const_colorp palette = png_ptr->palette;
png_bytep riffled_palette = png_ptr->riffled_palette;
png_const_bytep trans_alpha = png_ptr->trans_alpha;
int num_trans = png_ptr->num_trans;
int i;
/* Initially black, opaque. */
uint8x16x4_t w = {{
vdupq_n_u8(0x00),
vdupq_n_u8(0x00),
vdupq_n_u8(0x00),
vdupq_n_u8(0xff),
}};
png_debug(1, "in png_riffle_palette_neon");
/* First, riffle the RGB colours into an RGBA8 palette.
* The alpha component is set to opaque for now.
*/
for (i = 0; i < 256; i += 16)
{
uint8x16x3_t v = vld3q_u8((png_const_bytep)(palette + i));
w.val[0] = v.val[0];
w.val[1] = v.val[1];
w.val[2] = v.val[2];
vst4q_u8(riffled_palette + i * 4, w);
}
/* Fix up the missing transparency values. */
for (i = 0; i < num_trans; i++)
riffled_palette[i * 4 + 3] = trans_alpha[i];
}
/* Expands a palettized row into RGBA8. */
int
png_do_expand_palette_rgba8_neon(png_structrp png_ptr, png_row_infop row_info,
png_const_bytep row, png_bytepp ssp, png_bytepp ddp)
{
png_uint_32 row_width = row_info->width;
const png_uint_32 *riffled_palette =
png_aligncastconst(png_const_uint_32p, png_ptr->riffled_palette);
const png_uint_32 pixels_per_chunk = 4;
png_uint_32 i;
png_debug(1, "in png_do_expand_palette_rgba8_neon");
PNG_UNUSED(row)
if (row_width < pixels_per_chunk)
return 0;
/* This function originally gets the last byte of the output row.
* The NEON part writes forward from a given position, so we have
* to seek this back by 4 pixels x 4 bytes.
*/
*ddp = *ddp - (pixels_per_chunk * 4 - 1);
for (i = 0; i + pixels_per_chunk <= row_width; i += pixels_per_chunk)
{
uint32x4_t cur;
png_bytep sp = *ssp - i, dp = *ddp - i * 4;
cur = vld1q_dup_u32 (riffled_palette + *(sp - 3));
cur = vld1q_lane_u32(riffled_palette + *(sp - 2), cur, 1);
cur = vld1q_lane_u32(riffled_palette + *(sp - 1), cur, 2);
cur = vld1q_lane_u32(riffled_palette + *(sp - 0), cur, 3);
vst1q_u32((void *)dp, cur);
}
/* Undo the pre-adjustment of *ddp before the pointer handoff,
* so the scalar fallback in pngrtran.c receives a dp that points
* to the correct position.
*/
*ddp = *ddp + (pixels_per_chunk * 4 - 1);
*ssp = *ssp - i;
*ddp = *ddp - i * 4;
return i;
}
/* Expands a palettized row into RGB8. */
int
png_do_expand_palette_rgb8_neon(png_structrp png_ptr, png_row_infop row_info,
png_const_bytep row, png_bytepp ssp, png_bytepp ddp)
{
png_uint_32 row_width = row_info->width;
png_const_bytep palette = (png_const_bytep)png_ptr->palette;
const png_uint_32 pixels_per_chunk = 8;
png_uint_32 i;
png_debug(1, "in png_do_expand_palette_rgb8_neon");
PNG_UNUSED(row)
if (row_width <= pixels_per_chunk)
return 0;
/* Seeking this back by 8 pixels x 3 bytes. */
*ddp = *ddp - (pixels_per_chunk * 3 - 1);
for (i = 0; i + pixels_per_chunk <= row_width; i += pixels_per_chunk)
{
uint8x8x3_t cur;
png_bytep sp = *ssp - i, dp = *ddp - i * 3;
cur = vld3_dup_u8(palette + *(sp - 7) * 3);
cur = vld3_lane_u8(palette + *(sp - 6) * 3, cur, 1);
cur = vld3_lane_u8(palette + *(sp - 5) * 3, cur, 2);
cur = vld3_lane_u8(palette + *(sp - 4) * 3, cur, 3);
cur = vld3_lane_u8(palette + *(sp - 3) * 3, cur, 4);
cur = vld3_lane_u8(palette + *(sp - 2) * 3, cur, 5);
cur = vld3_lane_u8(palette + *(sp - 1) * 3, cur, 6);
cur = vld3_lane_u8(palette + *(sp - 0) * 3, cur, 7);
vst3_u8((void *)dp, cur);
}
/* Undo the pre-adjustment of *ddp before the pointer handoff,
* so the scalar fallback in pngrtran.c receives a dp that points
* to the correct position.
*/
*ddp = *ddp + (pixels_per_chunk * 3 - 1);
*ssp = *ssp - i;
*ddp = *ddp - i * 3;
return i;
}
#endif /* PNG_ARM_NEON_IMPLEMENTATION */
@@ -0,0 +1,417 @@
/* filter_lsx_intrinsics.c - LSX optimized filter functions
*
* Copyright (c) 2021 Loongson Technology Corporation Limited
* All rights reserved.
* Copyright (c) 2018 Cosmin Truta
* Copyright (c) 2016 Glenn Randers-Pehrson
* Contributed by Jin Bo (jinbo@loongson.cn)
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
#include "../pngpriv.h"
#ifdef PNG_READ_SUPPORTED
#if PNG_LOONGARCH_LSX_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */
#include <lsxintrin.h>
#define LSX_LD(psrc) __lsx_vld((psrc), 0)
#define LSX_LD_2(psrc, stride, out0, out1) \
{ \
out0 = LSX_LD(psrc); \
out1 = LSX_LD(psrc + stride); \
}
#define LSX_LD_4(psrc, stride, out0, out1, out2, out3) \
{ \
LSX_LD_2(psrc, stride, out0, out1); \
LSX_LD_2(psrc + stride * 2, stride, out2, out3); \
}
#define LSX_ST(in, pdst) __lsx_vst(in, (pdst), 0)
#define LSX_ST_2(in0, in1, pdst, stride) \
{ \
LSX_ST(in0, pdst); \
LSX_ST(in1, pdst + stride); \
}
#define LSX_ST_4(in0, in1, in2, in3, pdst, stride) \
{ \
LSX_ST_2(in0, in1, pdst, stride); \
LSX_ST_2(in2, in3, pdst + stride * 2, stride); \
}
#define LSX_ADD_B(in0, in1, out0) \
{ \
out0 = __lsx_vadd_b(in0, in1); \
}
#define LSX_ADD_B_2(in0, in1, in2, in3, out0, out1) \
{ \
LSX_ADD_B(in0, in1, out0); \
LSX_ADD_B(in2, in3, out1); \
}
#define LSX_ADD_B_4(in0, in1, in2, in3, in4, in5, \
in6, in7, out0, out1, out2, out3) \
{ \
LSX_ADD_B_2(in0, in1, in2, in3, out0, out1); \
LSX_ADD_B_2(in4, in5, in6, in7, out2, out3); \
}
#define LSX_ABS_B_3(in0, in1, in2, out0, out1, out2) \
{ \
out0 = __lsx_vadda_h(in0, zero); \
out1 = __lsx_vadda_h(in1, zero); \
out2 = __lsx_vadda_h(in2, zero); \
}
#define LSX_ILVL_B(in_h, in_l, out0) \
{ \
out0 = __lsx_vilvl_b(in_h, in_l); \
}
#define LSX_ILVL_B_2(in0_h, in0_l, in1_h, in1_l, out0, out1) \
{ \
LSX_ILVL_B(in0_h, in0_l, out0); \
LSX_ILVL_B(in1_h, in1_l, out1); \
}
#define LSX_HSUB_HU_BU_2(in0, in1, out0, out1) \
{ \
out0 = __lsx_vhsubw_hu_bu(in0, in0); \
out1 = __lsx_vhsubw_hu_bu(in1, in1); \
}
#define LSX_CMP_PICK_SMALLER(in0, in1, in2, in3, in4, in5, out0) \
{ \
__m128i _cmph, _cmpb, _in0, _in3; \
_cmph = __lsx_vslt_h(in1, in0); \
_cmpb = __lsx_vpickev_b(_cmph, _cmph); \
_in0 = __lsx_vmin_bu(in0,in1); \
_in3 = __lsx_vbitsel_v(in3, in4, _cmpb); \
_cmph = __lsx_vslt_h(in2, _in0); \
_cmpb = __lsx_vpickev_b(_cmph, _cmph); \
_in3 = __lsx_vbitsel_v(_in3, in5, _cmpb); \
out0 = __lsx_vadd_b(out0, _in3); \
}
void
png_read_filter_row_up_lsx(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
size_t n = row_info->rowbytes;
png_bytep rp = row;
png_const_bytep pp = prev_row;
__m128i vec_0, vec_1, vec_2, vec_3;
__m128i vec_4, vec_5, vec_6, vec_7;
while (n >= 64)
{
LSX_LD_4(rp, 16, vec_0, vec_1, vec_2, vec_3);
LSX_LD_4(pp, 16, vec_4, vec_5, vec_6, vec_7);
pp += 64;
LSX_ADD_B_4(vec_0 ,vec_4, vec_1, vec_5, vec_2, vec_6,
vec_3, vec_7, vec_0, vec_1, vec_2, vec_3);
LSX_ST_4(vec_0, vec_1, vec_2, vec_3, rp, 16);
rp += 64;
n -= 64;
}
if (n & 63)
{
if (n >= 32)
{
LSX_LD_2(rp, 16, vec_0, vec_1);
LSX_LD_2(pp, 16, vec_2, vec_3);
pp += 32;
LSX_ADD_B_2(vec_0, vec_2, vec_1, vec_3, vec_0, vec_1);
LSX_ST_2(vec_0, vec_1, rp, 16);
rp += 32;
n -= 32;
}
if (n & 31)
{
if (n >= 16)
{
vec_0 = LSX_LD(rp);
vec_1 = LSX_LD(pp);
pp += 16;
LSX_ADD_B(vec_0, vec_1, vec_0);
LSX_ST(vec_0, rp);
rp += 16;
n -= 16;
}
if (n >= 8)
{
vec_0 = __lsx_vldrepl_d(rp, 0);
vec_1 = __lsx_vldrepl_d(pp, 0);
vec_0 = __lsx_vadd_b(vec_0, vec_1);
__lsx_vstelm_d(vec_0, rp, 0, 0);
rp += 8;
pp += 8;
n -= 8;
}
while (n--)
{
*rp = *rp + *pp++;
rp++;
}
}
}
}
void
png_read_filter_row_sub3_lsx(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
size_t n = row_info->rowbytes;
png_uint_32 tmp;
png_bytep nxt = row;
__m128i vec_0, vec_1;
PNG_UNUSED(prev_row);
vec_0 = __lsx_vldrepl_w(nxt, 0);
nxt += 3;
n -= 3;
while (n >= 3)
{
vec_1 = __lsx_vldrepl_w(nxt, 0);
vec_1 = __lsx_vadd_b(vec_1, vec_0);
__lsx_vstelm_h(vec_1, nxt, 0, 0);
vec_0 = vec_1;
nxt += 2;
__lsx_vstelm_b(vec_1, nxt, 0, 2);
nxt += 1;
n -= 3;
}
row = nxt - 3;
while (n--)
{
*nxt = *nxt + *row++;
nxt++;
}
}
void
png_read_filter_row_sub4_lsx(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
size_t n = row_info->rowbytes;
__m128i vec_0, vec_1;
PNG_UNUSED(prev_row);
vec_0 = __lsx_vldrepl_w(row, 0);
row += 4;
n -= 4;
while (n >= 4)
{
vec_1 = __lsx_vldrepl_w(row, 0);
vec_1 = __lsx_vadd_b(vec_1, vec_0);
__lsx_vstelm_w(vec_1, row, 0, 0);
vec_0 = vec_1;
row += 4;
n -= 4;
}
}
void
png_read_filter_row_avg3_lsx(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
size_t n = row_info->rowbytes;
png_bytep nxt = row;
png_const_bytep prev_nxt = prev_row;
__m128i vec_0, vec_1, vec_2;
vec_0 = __lsx_vldrepl_w(nxt, 0);
vec_1 = __lsx_vldrepl_w(prev_nxt, 0);
prev_nxt += 3;
vec_1 = __lsx_vsrli_b(vec_1, 1);
vec_1 = __lsx_vadd_b(vec_1, vec_0);
__lsx_vstelm_h(vec_1, nxt, 0, 0);
nxt += 2;
__lsx_vstelm_b(vec_1, nxt, 0, 2);
nxt += 1;
n -= 3;
while (n >= 3)
{
vec_2 = vec_1;
vec_0 = __lsx_vldrepl_w(nxt, 0);
vec_1 = __lsx_vldrepl_w(prev_nxt, 0);
prev_nxt += 3;
vec_1 = __lsx_vavg_bu(vec_1, vec_2);
vec_1 = __lsx_vadd_b(vec_1, vec_0);
__lsx_vstelm_h(vec_1, nxt, 0, 0);
nxt += 2;
__lsx_vstelm_b(vec_1, nxt, 0, 2);
nxt += 1;
n -= 3;
}
row = nxt - 3;
while (n--)
{
vec_2 = __lsx_vldrepl_b(row, 0);
row++;
vec_0 = __lsx_vldrepl_b(nxt, 0);
vec_1 = __lsx_vldrepl_b(prev_nxt, 0);
prev_nxt++;
vec_1 = __lsx_vavg_bu(vec_1, vec_2);
vec_1 = __lsx_vadd_b(vec_1, vec_0);
__lsx_vstelm_b(vec_1, nxt, 0, 0);
nxt++;
}
}
void
png_read_filter_row_avg4_lsx(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
size_t n = row_info->rowbytes;
__m128i vec_0, vec_1, vec_2;
vec_0 = __lsx_vldrepl_w(row, 0);
vec_1 = __lsx_vldrepl_w(prev_row, 0);
prev_row += 4;
vec_1 = __lsx_vsrli_b(vec_1, 1);
vec_1 = __lsx_vadd_b(vec_1, vec_0);
__lsx_vstelm_w(vec_1, row, 0, 0);
row += 4;
n -= 4;
while (n >= 4)
{
vec_2 = vec_1;
vec_0 = __lsx_vldrepl_w(row, 0);
vec_1 = __lsx_vldrepl_w(prev_row, 0);
prev_row += 4;
vec_1 = __lsx_vavg_bu(vec_1, vec_2);
vec_1 = __lsx_vadd_b(vec_1, vec_0);
__lsx_vstelm_w(vec_1, row, 0, 0);
row += 4;
n -= 4;
}
}
void
png_read_filter_row_paeth3_lsx(png_row_infop row_info,
png_bytep row, png_const_bytep prev_row)
{
size_t n = row_info->rowbytes;
png_bytep nxt = row;
png_const_bytep prev_nxt = prev_row;
__m128i vec_a, vec_b, vec_c, vec_d;
__m128i vec_pa, vec_pb, vec_pc;
__m128i zero = {0};
vec_a = __lsx_vldrepl_w(nxt, 0);
vec_b = __lsx_vldrepl_w(prev_nxt, 0);
prev_nxt += 3;
vec_d = __lsx_vadd_b(vec_a, vec_b);
__lsx_vstelm_h(vec_d, nxt, 0, 0);
nxt += 2;
__lsx_vstelm_b(vec_d, nxt, 0, 2);
nxt += 1;
n -= 3;
while (n >= 3)
{
vec_a = vec_d;
vec_c = vec_b;
vec_b = __lsx_vldrepl_w(prev_nxt, 0);
prev_nxt += 3;
vec_d = __lsx_vldrepl_w(nxt, 0);
LSX_ILVL_B_2(vec_b, vec_c, vec_a, vec_c, vec_pa, vec_pb);
LSX_HSUB_HU_BU_2(vec_pa, vec_pb, vec_pa, vec_pb);
vec_pc = __lsx_vadd_h(vec_pa, vec_pb);
LSX_ABS_B_3(vec_pa, vec_pb, vec_pc, vec_pa, vec_pb, vec_pc);
LSX_CMP_PICK_SMALLER(vec_pa, vec_pb, vec_pc, vec_a, vec_b, vec_c, vec_d);
__lsx_vstelm_h(vec_d, nxt, 0, 0);
nxt += 2;
__lsx_vstelm_b(vec_d, nxt, 0, 2);
nxt += 1;
n -= 3;
}
prev_row = prev_nxt - 3;
row = nxt - 3;
while (n--)
{
vec_a = __lsx_vldrepl_b(row, 0);
row++;
vec_b = __lsx_vldrepl_b(prev_nxt, 0);
prev_nxt++;
vec_c = __lsx_vldrepl_b(prev_row, 0);
prev_row++;
vec_d = __lsx_vldrepl_b(nxt, 0);
LSX_ILVL_B_2(vec_b, vec_c, vec_a, vec_c, vec_pa, vec_pb);
LSX_HSUB_HU_BU_2(vec_pa, vec_pb, vec_pa, vec_pb);
vec_pc = __lsx_vadd_h(vec_pa, vec_pb);
LSX_ABS_B_3(vec_pa, vec_pb, vec_pc, vec_pa, vec_pb, vec_pc);
LSX_CMP_PICK_SMALLER(vec_pa, vec_pb, vec_pc, vec_a, vec_b, vec_c, vec_d);
__lsx_vstelm_b(vec_d, nxt, 0, 0);
nxt++;
}
}
void
png_read_filter_row_paeth4_lsx(png_row_infop row_info,
png_bytep row, png_const_bytep prev_row)
{
size_t n = row_info->rowbytes;
__m128i vec_a, vec_b, vec_c, vec_d;
__m128i vec_pa, vec_pb, vec_pc;
__m128i zero = {0};
vec_a = __lsx_vldrepl_w(row, 0);
vec_b = __lsx_vldrepl_w(prev_row, 0);
prev_row += 4;
vec_d = __lsx_vadd_b(vec_a, vec_b);
__lsx_vstelm_w(vec_d, row, 0, 0);
row += 4;
n -= 4;
while (n >= 4)
{
vec_a = vec_d;
vec_c = vec_b;
vec_b = __lsx_vldrepl_w(prev_row, 0);
prev_row += 4;
vec_d = __lsx_vldrepl_w(row, 0);
LSX_ILVL_B_2(vec_b, vec_c, vec_a, vec_c, vec_pa, vec_pb);
LSX_HSUB_HU_BU_2(vec_pa, vec_pb, vec_pa, vec_pb);
vec_pc = __lsx_vadd_h(vec_pa, vec_pb);
LSX_ABS_B_3(vec_pa, vec_pb, vec_pc, vec_pa, vec_pb, vec_pc);
LSX_CMP_PICK_SMALLER(vec_pa, vec_pb, vec_pc, vec_a, vec_b, vec_c, vec_d);
__lsx_vstelm_w(vec_d, row, 0, 0);
row += 4;
n -= 4;
}
}
#endif /* PNG_LOONGARCH_LSX_IMPLEMENTATION == 1 (intrinsics) */
#endif /* PNG_READ_SUPPORTED */
@@ -0,0 +1,66 @@
/* loongarch_lsx_init.c - LSX optimized filter functions
*
* Copyright (c) 2021 Loongson Technology Corporation Limited
* All rights reserved.
* Contributed by Jin Bo <jinbo@loongson.cn>
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
#include "../pngpriv.h"
#ifdef PNG_READ_SUPPORTED
#if PNG_LOONGARCH_LSX_IMPLEMENTATION == 1
#include <sys/auxv.h>
#define LA_HWCAP_LSX (1<<4)
static int
png_has_lsx(void)
{
int flags = 0;
int flag = (int)getauxval(AT_HWCAP);
if (flag & LA_HWCAP_LSX)
return 1;
return 0;
}
void
png_init_filter_functions_lsx(png_structp pp, unsigned int bpp)
{
/* IMPORTANT: any new external functions used here must be declared using
* PNG_INTERNAL_FUNCTION in ../pngpriv.h. This is required so that the
* 'prefix' option to configure works:
*
* ./configure --with-libpng-prefix=foobar_
*
* Verify you have got this right by running the above command, doing a build
* and examining pngprefix.h; it must contain a #define for every external
* function you add. (Notice that this happens automatically for the
* initialization function.)
*/
if (png_has_lsx())
{
pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_lsx;
if (bpp == 3)
{
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_lsx;
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_lsx;
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth3_lsx;
}
else if (bpp == 4)
{
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_lsx;
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_lsx;
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth4_lsx;
}
}
}
#endif /* PNG_LOONGARCH_LSX_IMPLEMENTATION == 1 */
#endif /* PNG_READ_SUPPORTED */
+15 -5
View File
@@ -9,7 +9,7 @@ EXPORTS += [
'pnglibconf.h'
]
UNIFIED_SOURCES += [
SOURCES += [
'png.c',
'pngerror.c',
'pngget.c',
@@ -26,11 +26,12 @@ UNIFIED_SOURCES += [
'pngwutil.c'
]
if CONFIG['CPU_ARCH'] == 'arm':
if CONFIG['CPU_ARCH'] in ('arm','aarch64'):
DEFINES['MOZ_PNG_USE_ARM_NEON'] = True
UNIFIED_SOURCES += [
SOURCES += [
'arm/arm_init.c',
'arm/filter_neon_intrinsics.c'
'arm/filter_neon_intrinsics.c',
'arm/palette_neon_intrinsics.c'
]
SOURCES += [
@@ -39,11 +40,20 @@ if CONFIG['CPU_ARCH'] == 'arm':
if CONFIG['INTEL_ARCHITECTURE']:
DEFINES['MOZ_PNG_USE_INTEL_SSE'] = True
UNIFIED_SOURCES += [
SOURCES += [
'sse2/filter_sse2_intrinsics.c',
'sse2/intel_init.c'
]
if CONFIG['CPU_ARCH'] == 'loongarch64':
DEFINES['PNG_LOONGARCH_LSX_OPT'] = 1
SOURCES += [
'loongarch/filter_lsx_intrinsics.c',
'loongarch/loongarch_lsx_init.c',
]
SOURCES['loongarch/filter_lsx_intrinsics.c'].flags += ['-mlsx']
SOURCES['loongarch/loongarch_lsx_init.c'].flags += ['-mlsx']
Library('mozpng')
if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
+620 -1110
View File
File diff suppressed because it is too large. Load diff
+935 -686
View File
File diff suppressed because it is too large. Load diff
+47 -54
View File
@@ -1,11 +1,11 @@
/* pngconf.h - machine configurable file for libpng
/* pngconf.h - machine-configurable file for libpng
*
* libpng version 1.6.26, October 20, 2016
* libpng version 1.6.58
*
* Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
* Copyright (c) 2018-2026 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -57,14 +57,13 @@
#endif /* PNG_BUILDING_SYMBOL_TABLE */
/* Prior to 1.6.0 it was possible to turn off 'const' in declarations using
* PNG_NO_CONST; this is no longer supported except for data declarations which
* apparently still cause problems in 2011 on some compilers.
/* Prior to 1.6.0, it was possible to turn off 'const' in declarations,
* using PNG_NO_CONST. This is no longer supported.
*/
#define PNG_CONST const /* backward compatibility only */
/* This controls optimization of the reading of 16-bit and 32-bit values
* from PNG files. It can be set on a per-app-file basis - it
/* This controls optimization of the reading of 16-bit and 32-bit
* values from PNG files. It can be set on a per-app-file basis: it
* just changes whether a macro is used when the function is called.
* The library builder sets the default; if read functions are not
* built into the library the macro implementation is forced on.
@@ -88,7 +87,7 @@
/* The PNGARG macro was used in versions of libpng prior to 1.6.0 to protect
* against legacy (pre ISOC90) compilers that did not understand function
* prototypes. It is not required for modern C compilers.
* prototypes. [Deprecated.]
*/
#ifndef PNGARG
# define PNGARG(arglist) arglist
@@ -127,7 +126,7 @@
*
* These cases only differ if the operating system does not use the C
* calling convention, at present this just means the above cases
* (x86 DOS/Windows sytems) and, even then, this does not apply to
* (x86 DOS/Windows systems) and, even then, this does not apply to
* Cygwin running on those systems.
*
* Note that the value must be defined in pnglibconf.h so that what
@@ -180,8 +179,8 @@
* compiler-specific macros to the values required to change the calling
* conventions of the various functions.
*/
#if defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\
defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
#if defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || \
defined(__CYGWIN__)
/* Windows system (DOS doesn't support DLLs). Includes builds under Cygwin or
* MinGW on any architecture currently supported by Windows. Also includes
* Watcom builds but these need special treatment because they are not
@@ -220,25 +219,13 @@
/* NOTE: PNGCBAPI always defaults to PNGCAPI. */
# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD)
# error "PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed"
# error PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed
# endif
# if (defined(_MSC_VER) && _MSC_VER < 800) ||\
(defined(__BORLANDC__) && __BORLANDC__ < 0x500)
/* older Borland and MSC
* compilers used '__export' and required this to be after
* the type.
*/
# ifndef PNG_EXPORT_TYPE
# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP
# endif
# define PNG_DLL_EXPORT __export
# else /* newer compiler */
# define PNG_DLL_EXPORT __declspec(dllexport)
# ifndef PNG_DLL_IMPORT
# define PNG_DLL_IMPORT __declspec(dllimport)
# endif
# endif /* compiler */
# define PNG_DLL_EXPORT __declspec(dllexport)
# ifndef PNG_DLL_IMPORT
# define PNG_DLL_IMPORT __declspec(dllimport)
# endif
#else /* !Windows */
# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__)
@@ -298,7 +285,7 @@
#ifndef PNG_EXPORTA
# define PNG_EXPORTA(ordinal, type, name, args, attributes) \
PNG_FUNCTION(PNG_EXPORT_TYPE(type), (PNGAPI name), PNGARG(args), \
PNG_FUNCTION(PNG_EXPORT_TYPE(type), (PNGAPI name), args, \
PNG_LINKAGE_API attributes)
#endif
@@ -316,7 +303,7 @@
#endif
#ifndef PNG_CALLBACK
# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args)
# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) args
#endif
/* Support for compiler specific function attributes. These are used
@@ -480,7 +467,7 @@
#if CHAR_BIT == 8 && UCHAR_MAX == 255
typedef unsigned char png_byte;
#else
# error "libpng requires 8-bit bytes"
# error libpng requires 8-bit bytes
#endif
#if INT_MIN == -32768 && INT_MAX == 32767
@@ -488,7 +475,7 @@
#elif SHRT_MIN == -32768 && SHRT_MAX == 32767
typedef short png_int_16;
#else
# error "libpng requires a signed 16-bit type"
# error libpng requires a signed 16-bit integer type
#endif
#if UINT_MAX == 65535
@@ -496,7 +483,7 @@
#elif USHRT_MAX == 65535
typedef unsigned short png_uint_16;
#else
# error "libpng requires an unsigned 16-bit type"
# error libpng requires an unsigned 16-bit integer type
#endif
#if INT_MIN < -2147483646 && INT_MAX > 2147483646
@@ -504,7 +491,7 @@
#elif LONG_MIN < -2147483646 && LONG_MAX > 2147483646
typedef long int png_int_32;
#else
# error "libpng requires a signed 32-bit (or more) type"
# error libpng requires a signed 32-bit (or longer) integer type
#endif
#if UINT_MAX > 4294967294U
@@ -512,11 +499,13 @@
#elif ULONG_MAX > 4294967294U
typedef unsigned long int png_uint_32;
#else
# error "libpng requires an unsigned 32-bit (or more) type"
# error libpng requires an unsigned 32-bit (or longer) integer type
#endif
/* Prior to 1.6.0 it was possible to disable the use of size_t, 1.6.0, however,
* requires an ISOC90 compiler and relies on consistent behavior of sizeof.
/* Prior to 1.6.0, it was possible to disable the use of size_t and ptrdiff_t.
* From 1.6.0 onwards, an ISO C90 compiler, as well as a standard-compliant
* behavior of sizeof and ptrdiff_t are required.
* The legacy typedefs are provided here for backwards compatibility.
*/
typedef size_t png_size_t;
typedef ptrdiff_t png_ptrdiff_t;
@@ -537,13 +526,12 @@ typedef ptrdiff_t png_ptrdiff_t;
# endif
#endif
/* png_alloc_size_t is guaranteed to be no smaller than png_size_t, and no
* smaller than png_uint_32. Casts from png_size_t or png_uint_32 to
* png_alloc_size_t are not necessary; in fact, it is recommended not to use
* them at all so that the compiler can complain when something turns out to be
* problematic.
/* png_alloc_size_t is guaranteed to be no smaller than size_t, and no smaller
* than png_uint_32. Casts from size_t or png_uint_32 to png_alloc_size_t are
* not necessary; in fact, it is recommended not to use them at all, so that
* the compiler can complain when something turns out to be problematic.
*
* Casts in the other direction (from png_alloc_size_t to png_size_t or
* Casts in the other direction (from png_alloc_size_t to size_t or
* png_uint_32) should be explicitly applied; however, we do not expect to
* encounter practical situations that require such conversions.
*
@@ -553,7 +541,7 @@ typedef ptrdiff_t png_ptrdiff_t;
#ifdef PNG_SMALL_SIZE_T
typedef png_uint_32 png_alloc_size_t;
#else
typedef png_size_t png_alloc_size_t;
typedef size_t png_alloc_size_t;
#endif
/* Prior to 1.6.0 libpng offered limited support for Microsoft C compiler
@@ -589,12 +577,8 @@ typedef char * png_charp;
typedef const char * png_const_charp;
typedef png_fixed_point * png_fixed_point_p;
typedef const png_fixed_point * png_const_fixed_point_p;
typedef png_size_t * png_size_tp;
typedef const png_size_t * png_const_size_tp;
#ifdef PNG_STDIO_SUPPORTED
typedef FILE * png_FILE_p;
#endif
typedef size_t * png_size_tp;
typedef const size_t * png_const_size_tp;
#ifdef PNG_FLOATING_POINT_SUPPORTED
typedef double * png_doublep;
@@ -617,6 +601,15 @@ typedef double * * png_doublepp;
/* Pointers to pointers to pointers; i.e., pointer to array */
typedef char * * * png_charppp;
#ifdef PNG_STDIO_SUPPORTED
/* With PNG_STDIO_SUPPORTED it was possible to use I/O streams that were
* not necessarily stdio FILE streams, to allow building Windows applications
* before Win32 and Windows CE applications before WinCE 3.0, but that kind
* of support has long been discontinued.
*/
typedef FILE * png_FILE_p; /* [Deprecated] */
#endif
#endif /* PNG_BUILDING_SYMBOL_TABLE */
#endif /* PNGCONF_H */
+8 -8
View File
@@ -1,16 +1,19 @@
/* pngdebug.h - Debugging macros for libpng, also used in pngtest.c
/* pngdebug.h - internal debugging macros for libpng
*
* Last changed in libpng 1.6.8 [December 19, 2013]
* Copyright (c) 2018-2025 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2013 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
#ifndef PNGPRIV_H
# error This file must not be included by applications; please include <png.h>
#endif
/* Define PNG_DEBUG at compile time for debugging information. Higher
* numbers for PNG_DEBUG mean more debugging information. This has
* only been added since version 0.95 so it is not implemented throughout
@@ -35,9 +38,6 @@
#define PNGDEBUG_H
/* These settings control the formatting of messages in png.c and pngerror.c */
/* Moved to pngdebug.h at 1.5.0 */
# ifndef PNG_LITERAL_SHARP
# define PNG_LITERAL_SHARP 0x23
# endif
# ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET
# define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5b
# endif
+54 -167
View File
@@ -1,10 +1,9 @@
/* pngerror.c - stub functions for i/o and memory allocation
*
* Last changed in libpng 1.6.26 [October 20, 2016]
* Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
* Copyright (c) 2018-2025 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -20,13 +19,14 @@
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
static PNG_FUNCTION(void, png_default_error,PNGARG((png_const_structrp png_ptr,
png_const_charp error_message)),PNG_NORETURN);
static PNG_FUNCTION(void /* PRIVATE */,
png_default_error,(png_const_structrp png_ptr, png_const_charp error_message),
PNG_NORETURN);
#ifdef PNG_WARNINGS_SUPPORTED
static void /* PRIVATE */
png_default_warning PNGARG((png_const_structrp png_ptr,
png_const_charp warning_message));
png_default_warning(png_const_structrp png_ptr,
png_const_charp warning_message);
#endif /* WARNINGS */
/* This function is called whenever there is a fatal error. This function
@@ -39,46 +39,6 @@ PNG_FUNCTION(void,PNGAPI
png_error,(png_const_structrp png_ptr, png_const_charp error_message),
PNG_NORETURN)
{
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
char msg[16];
if (png_ptr != NULL)
{
if ((png_ptr->flags &
(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0)
{
if (*error_message == PNG_LITERAL_SHARP)
{
/* Strip "#nnnn " from beginning of error message. */
int offset;
for (offset = 1; offset<15; offset++)
if (error_message[offset] == ' ')
break;
if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0)
{
int i;
for (i = 0; i < offset - 1; i++)
msg[i] = error_message[i + 1];
msg[i - 1] = '\0';
error_message = msg;
}
else
error_message += offset;
}
else
{
if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0)
{
msg[0] = '0';
msg[1] = '\0';
error_message = msg;
}
}
}
}
#endif
if (png_ptr != NULL && png_ptr->error_fn != NULL)
(*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr),
error_message);
@@ -89,7 +49,8 @@ png_error,(png_const_structrp png_ptr, png_const_charp error_message),
}
#else
PNG_FUNCTION(void,PNGAPI
png_err,(png_const_structrp png_ptr),PNG_NORETURN)
png_err,(png_const_structrp png_ptr),
PNG_NORETURN)
{
/* Prior to 1.5.2 the error_fn received a NULL pointer, expressed
* erroneously as '\0', instead of the empty string "". This was
@@ -163,7 +124,7 @@ png_format_number(png_const_charp start, png_charp end, int format,
case PNG_NUMBER_FORMAT_02u:
/* Expects at least 2 digits. */
mincount = 2;
/* FALL THROUGH */
/* FALLTHROUGH */
case PNG_NUMBER_FORMAT_u:
*--end = digits[number % 10];
@@ -173,7 +134,7 @@ png_format_number(png_const_charp start, png_charp end, int format,
case PNG_NUMBER_FORMAT_02x:
/* This format expects at least two digits */
mincount = 2;
/* FALL THROUGH */
/* FALLTHROUGH */
case PNG_NUMBER_FORMAT_x:
*--end = digits[number & 0xf];
@@ -216,21 +177,6 @@ void PNGAPI
png_warning(png_const_structrp png_ptr, png_const_charp warning_message)
{
int offset = 0;
if (png_ptr != NULL)
{
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
if ((png_ptr->flags &
(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0)
#endif
{
if (*warning_message == PNG_LITERAL_SHARP)
{
for (offset = 1; offset < 15; offset++)
if (warning_message[offset] == ' ')
break;
}
}
}
if (png_ptr != NULL && png_ptr->warning_fn != NULL)
(*(png_ptr->warning_fn))(png_constcast(png_structrp,png_ptr),
warning_message + offset);
@@ -255,7 +201,7 @@ void
png_warning_parameter_unsigned(png_warning_parameters p, int number, int format,
png_alloc_size_t value)
{
char buffer[PNG_NUMBER_BUFFER_SIZE];
char buffer[PNG_NUMBER_BUFFER_SIZE] = {0};
png_warning_parameter(p, number, PNG_FORMAT_NUMBER(buffer, format, value));
}
@@ -265,7 +211,7 @@ png_warning_parameter_signed(png_warning_parameters p, int number, int format,
{
png_alloc_size_t u;
png_charp str;
char buffer[PNG_NUMBER_BUFFER_SIZE];
char buffer[PNG_NUMBER_BUFFER_SIZE] = {0};
/* Avoid overflow by doing the negate in a png_alloc_size_t: */
u = (png_alloc_size_t)value;
@@ -425,14 +371,14 @@ png_app_error(png_const_structrp png_ptr, png_const_charp error_message)
* if the character is invalid.
*/
#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
static PNG_CONST char png_digit[16] = {
static const char png_digit[16] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F'
};
static void /* PRIVATE */
png_format_buffer(png_const_structrp png_ptr, png_charp buffer, png_const_charp
error_message)
png_format_buffer(png_const_structrp png_ptr, png_charp buffer,
png_const_charp error_message)
{
png_uint_32 chunk_name = png_ptr->chunk_name;
int iout = 0, ishift = 24;
@@ -511,8 +457,8 @@ png_chunk_warning(png_const_structrp png_ptr, png_const_charp warning_message)
#ifdef PNG_READ_SUPPORTED
#ifdef PNG_BENIGN_ERRORS_SUPPORTED
void PNGAPI
png_chunk_benign_error(png_const_structrp png_ptr, png_const_charp
error_message)
png_chunk_benign_error(png_const_structrp png_ptr,
png_const_charp error_message)
{
if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0)
png_chunk_warning(png_ptr, error_message);
@@ -569,7 +515,8 @@ png_chunk_report(png_const_structrp png_ptr, png_const_charp message, int error)
#ifdef PNG_ERROR_TEXT_SUPPORTED
#ifdef PNG_FLOATING_POINT_SUPPORTED
PNG_FUNCTION(void,
png_fixed_error,(png_const_structrp png_ptr, png_const_charp name),PNG_NORETURN)
png_fixed_error,(png_const_structrp png_ptr, png_const_charp name),
PNG_NORETURN)
{
# define fixed_message "fixed point overflow in "
# define fixed_message_ln ((sizeof fixed_message)-1)
@@ -712,42 +659,9 @@ png_default_error,(png_const_structrp png_ptr, png_const_charp error_message),
PNG_NORETURN)
{
#ifdef PNG_CONSOLE_IO_SUPPORTED
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
/* Check on NULL only added in 1.5.4 */
if (error_message != NULL && *error_message == PNG_LITERAL_SHARP)
{
/* Strip "#nnnn " from beginning of error message. */
int offset;
char error_number[16];
for (offset = 0; offset<15; offset++)
{
error_number[offset] = error_message[offset + 1];
if (error_message[offset] == ' ')
break;
}
if ((offset > 1) && (offset < 15))
{
error_number[offset - 1] = '\0';
fprintf(stderr, "libpng error no. %s: %s",
error_number, error_message + offset + 1);
fprintf(stderr, PNG_STRING_NEWLINE);
}
else
{
fprintf(stderr, "libpng error: %s, offset=%d",
error_message, offset);
fprintf(stderr, PNG_STRING_NEWLINE);
}
}
else
#endif
{
fprintf(stderr, "libpng error: %s", error_message ? error_message :
"undefined");
fprintf(stderr, PNG_STRING_NEWLINE);
}
fprintf(stderr, "libpng error: %s", error_message ? error_message :
"undefined");
fprintf(stderr, PNG_STRING_NEWLINE);
#else
PNG_UNUSED(error_message) /* Make compiler happy */
#endif
@@ -755,7 +669,8 @@ png_default_error,(png_const_structrp png_ptr, png_const_charp error_message),
}
PNG_FUNCTION(void,PNGAPI
png_longjmp,(png_const_structrp png_ptr, int val),PNG_NORETURN)
png_longjmp,(png_const_structrp png_ptr, int val),
PNG_NORETURN)
{
#ifdef PNG_SETJMP_SUPPORTED
if (png_ptr != NULL && png_ptr->longjmp_fn != NULL &&
@@ -785,40 +700,8 @@ static void /* PRIVATE */
png_default_warning(png_const_structrp png_ptr, png_const_charp warning_message)
{
#ifdef PNG_CONSOLE_IO_SUPPORTED
# ifdef PNG_ERROR_NUMBERS_SUPPORTED
if (*warning_message == PNG_LITERAL_SHARP)
{
int offset;
char warning_number[16];
for (offset = 0; offset < 15; offset++)
{
warning_number[offset] = warning_message[offset + 1];
if (warning_message[offset] == ' ')
break;
}
if ((offset > 1) && (offset < 15))
{
warning_number[offset + 1] = '\0';
fprintf(stderr, "libpng warning no. %s: %s",
warning_number, warning_message + offset);
fprintf(stderr, PNG_STRING_NEWLINE);
}
else
{
fprintf(stderr, "libpng warning: %s",
warning_message);
fprintf(stderr, PNG_STRING_NEWLINE);
}
}
else
# endif
{
fprintf(stderr, "libpng warning: %s", warning_message);
fprintf(stderr, PNG_STRING_NEWLINE);
}
fprintf(stderr, "libpng warning: %s", warning_message);
fprintf(stderr, PNG_STRING_NEWLINE);
#else
PNG_UNUSED(warning_message) /* Make compiler happy */
#endif
@@ -858,7 +741,7 @@ png_get_error_ptr(png_const_structrp png_ptr)
if (png_ptr == NULL)
return NULL;
return ((png_voidp)png_ptr->error_ptr);
return (png_voidp)png_ptr->error_ptr;
}
@@ -866,12 +749,8 @@ png_get_error_ptr(png_const_structrp png_ptr)
void PNGAPI
png_set_strip_error_numbers(png_structrp png_ptr, png_uint_32 strip_mode)
{
if (png_ptr != NULL)
{
png_ptr->flags &=
((~(PNG_FLAG_STRIP_ERROR_NUMBERS |
PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode);
}
PNG_UNUSED(png_ptr)
PNG_UNUSED(strip_mode)
}
#endif
@@ -885,7 +764,7 @@ PNG_FUNCTION(void /* PRIVATE */, (PNGCBAPI
png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message),
PNG_NORETURN)
{
const png_const_structrp png_ptr = png_nonconst_ptr;
png_const_structrp png_ptr = png_nonconst_ptr;
png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr);
/* An error is always logged here, overwriting anything (typically a warning)
@@ -920,7 +799,7 @@ png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message),
void /* PRIVATE */ PNGCBAPI
png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message)
{
const png_const_structrp png_ptr = png_nonconst_ptr;
png_const_structrp png_ptr = png_nonconst_ptr;
png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr);
/* A warning is only logged if there is no prior warning or error. */
@@ -933,31 +812,39 @@ png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message)
#endif
int /* PRIVATE */
png_safe_execute(png_imagep image_in, int (*function)(png_voidp), png_voidp arg)
png_safe_execute(png_imagep image, int (*function)(png_voidp), png_voidp arg)
{
volatile png_imagep image = image_in;
volatile int result;
volatile png_voidp saved_error_buf;
const png_voidp saved_error_buf = image->opaque->error_buf;
jmp_buf safe_jmpbuf;
/* Safely execute function(arg) with png_error returning to this function. */
saved_error_buf = image->opaque->error_buf;
result = setjmp(safe_jmpbuf) == 0;
if (result != 0)
/* Safely execute function(arg), with png_error returning back here. */
if (setjmp(safe_jmpbuf) == 0)
{
int result;
image->opaque->error_buf = safe_jmpbuf;
result = function(arg);
image->opaque->error_buf = saved_error_buf;
if (result)
return 1; /* success */
}
/* The function failed either because of a caught png_error and a regular
* return of false above or because of an uncaught png_error from the
* function itself. Ensure that the error_buf is always set back to the
* value saved above:
*/
image->opaque->error_buf = saved_error_buf;
/* And do the cleanup prior to any failure return. */
if (result == 0)
/* On the final false return, when about to return control to the caller, the
* image is freed (png_image_free does this check but it is duplicated here
* for clarity:
*/
if (saved_error_buf == NULL)
png_image_free(image);
return result;
return 0; /* failure */
}
#endif /* SIMPLIFIED READ || SIMPLIFIED_WRITE */
#endif /* READ || WRITE */
+405 -255
View File
File diff suppressed because it is too large. Load diff
+62 -58
View File
@@ -1,53 +1,29 @@
/* pnginfo.h - header file for PNG reference library
/* pnginfo.h - internal structures for libpng
*
* Last changed in libpng 1.6.1 [March 28, 2013]
* Copyright (c) 1998-2002,2004,2006-2013 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
* Copyright (c) 2018-2025 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2013,2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
/* png_info is a structure that holds the information in a PNG file so
* that the application can find out the characteristics of the image.
* If you are reading the file, this structure will tell you what is
* in the PNG file. If you are writing the file, fill in the information
* you want to put into the PNG file, using png_set_*() functions, then
* call png_write_info().
#ifndef PNGPRIV_H
# error This file must not be included by applications; please include <png.h>
#endif
/* INTERNAL, PRIVATE definition of a PNG.
*
* The names chosen should be very close to the PNG specification, so
* consult that document for information about the meaning of each field.
* png_info is a modifiable description of a PNG datastream. The fields inside
* this structure are accessed through png_get_<CHUNK>() functions and modified
* using png_set_<CHUNK>() functions.
*
* With libpng < 0.95, it was only possible to directly set and read the
* the values in the png_info_struct, which meant that the contents and
* order of the values had to remain fixed. With libpng 0.95 and later,
* however, there are now functions that abstract the contents of
* png_info_struct from the application, so this makes it easier to use
* libpng with dynamic libraries, and even makes it possible to use
* libraries that don't have all of the libpng ancillary chunk-handing
* functionality. In libpng-1.5.0 this was moved into a separate private
* file that is not visible to applications.
*
* The following members may have allocated storage attached that should be
* cleaned up before the structure is discarded: palette, trans, text,
* pcal_purpose, pcal_units, pcal_params, hist, iccp_name, iccp_profile,
* splt_palettes, scal_unit, row_pointers, and unknowns. By default, these
* are automatically freed when the info structure is deallocated, if they were
* allocated internally by libpng. This behavior can be changed by means
* of the png_data_freer() function.
*
* More allocation details: all the chunk-reading functions that
* change these members go through the corresponding png_set_*
* functions. A function to clear these members is available: see
* png_free_data(). The png_set_* functions do not depend on being
* able to point info structure members to any of the storage they are
* passed (they make their own copies), EXCEPT that the png_set_text
* functions use the same storage passed to them in the text_ptr or
* itxt_ptr structure argument, and the png_set_rows and png_set_unknowns
* functions do not make their own copies.
* Some functions in libpng do directly access members of png_info. However,
* this should be avoided. png_struct objects contain members which hold
* caches, sometimes optimised, of the values from png_info objects, and
* png_info is not passed to the functions which read and write image data.
*/
#ifndef PNGINFO_H
#define PNGINFO_H
@@ -55,10 +31,10 @@
struct png_info_def
{
/* The following are necessary for every PNG file */
png_uint_32 width; /* width of image in pixels (from IHDR) */
png_uint_32 height; /* height of image in pixels (from IHDR) */
png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */
png_size_t rowbytes; /* bytes needed to hold an untransformed row */
png_uint_32 width; /* width of image in pixels (from IHDR) */
png_uint_32 height; /* height of image in pixels (from IHDR) */
png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */
size_t rowbytes; /* bytes needed to hold an untransformed row */
png_colorp palette; /* array of color values (valid & PNG_INFO_PLTE) */
png_uint_16 num_palette; /* number of color entries in "palette" (PLTE) */
png_uint_16 num_trans; /* number of transparent palette color (tRNS) */
@@ -87,18 +63,12 @@ struct png_info_def
* and initialize the appropriate fields below.
*/
#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
/* png_colorspace only contains 'flags' if neither GAMMA or COLORSPACE are
* defined. When COLORSPACE is switched on all the colorspace-defining
* chunks should be enabled, when GAMMA is switched on all the gamma-defining
* chunks should be enabled. If this is not done it becomes possible to read
* inconsistent PNG files and assign a probably incorrect interpretation to
* the information. (In other words, by carefully choosing which chunks to
* recognize the system configuration can select an interpretation for PNG
* files containing ambiguous data and this will result in inconsistent
* behavior between different libpng builds!)
*/
png_colorspace colorspace;
#ifdef PNG_cICP_SUPPORTED
/* cICP chunk data */
png_byte cicp_colour_primaries;
png_byte cicp_transfer_function;
png_byte cicp_matrix_coefficients;
png_byte cicp_video_full_range_flag;
#endif
#ifdef PNG_iCCP_SUPPORTED
@@ -108,6 +78,24 @@ struct png_info_def
png_uint_32 iccp_proflen; /* ICC profile data length */
#endif
#ifdef PNG_cLLI_SUPPORTED
png_uint_32 maxCLL; /* cd/m2 (nits) * 10,000 */
png_uint_32 maxFALL;
#endif
#ifdef PNG_mDCV_SUPPORTED
png_uint_16 mastering_red_x; /* CIE (xy) x * 50,000 */
png_uint_16 mastering_red_y;
png_uint_16 mastering_green_x;
png_uint_16 mastering_green_y;
png_uint_16 mastering_blue_x;
png_uint_16 mastering_blue_y;
png_uint_16 mastering_white_x;
png_uint_16 mastering_white_y;
png_uint_32 mastering_maxDL; /* cd/m2 (nits) * 10,000 */
png_uint_32 mastering_minDL;
#endif
#ifdef PNG_TEXT_SUPPORTED
/* The tEXt, and zTXt chunks contain human-readable textual data in
* uncompressed, compressed, and optionally compressed forms, respectively.
@@ -185,6 +173,11 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
png_byte phys_unit_type; /* resolution type (see PNG_RESOLUTION_ below) */
#endif
#ifdef PNG_eXIf_SUPPORTED
png_uint_32 num_exif; /* Added at libpng-1.6.31 */
png_bytep exif;
#endif
#ifdef PNG_hIST_SUPPORTED
/* The hIST chunk contains the relative frequency or importance of the
* various palette entries, so that a viewer can intelligently select a
@@ -239,7 +232,7 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
/* The sCAL chunk describes the actual physical dimensions of the
* subject matter of the graphic. The chunk contains a unit specification
* a byte value, and two ASCII strings representing floating-point
* values. The values are width and height corresponsing to one pixel
* values. The values are width and height corresponding to one pixel
* in the image. Data values are valid if (valid & PNG_INFO_sCAL) is
* non-zero.
*/
@@ -268,5 +261,16 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
png_byte next_frame_blend_op;
#endif
#ifdef PNG_cHRM_SUPPORTED
png_xy cHRM;
#endif
#ifdef PNG_gAMA_SUPPORTED
png_fixed_point gamma;
#endif
#ifdef PNG_sRGB_SUPPORTED
int rendering_intent;
#endif
};
#endif /* PNGINFO_H */
-15
View File
@@ -285,27 +285,15 @@
#define png_get_y_pixels_per_inch MOZ_PNG_get_y_pixels_per_inch
#define png_get_y_pixels_per_meter MOZ_PNG_get_y_pix_per_meter
#define png_handle_as_unknown MOZ_PNG_handle_as_unknown
#define png_handle_bKGD MOZ_PNG_handle_bKGD
#define png_handle_cHRM MOZ_PNG_handle_cHRM
#define png_handle_gAMA MOZ_PNG_handle_gAMA
#define png_handle_hIST MOZ_PNG_handle_hIST
#define png_handle_iCCP MOZ_PNG_handle_iCCP
#define png_handle_IEND MOZ_PNG_handle_IEND
#define png_handle_IHDR MOZ_PNG_handle_IHDR
#define png_handle_iTXt MOZ_PNG_handle_iTXt
#define png_handle_oFFs MOZ_PNG_handle_oFFs
#define png_handle_pCAL MOZ_PNG_handle_pCAL
#define png_handle_pHYs MOZ_PNG_handle_pHYs
#define png_handle_PLTE MOZ_PNG_handle_PLTE
#define png_handle_sBIT MOZ_PNG_handle_sBIT
#define png_handle_sCAL MOZ_PNG_handle_sCAL
#define png_handle_sPLT MOZ_PNG_handle_sPLT
#define png_handle_sRGB MOZ_PNG_handle_sRGB
#define png_handle_tEXt MOZ_PNG_handle_tEXt
#define png_handle_tIME MOZ_PNG_handle_tIME
#define png_handle_tRNS MOZ_PNG_handle_tRNS
#define png_handle_unknown MOZ_PNG_handle_unknown
#define png_handle_zTXt MOZ_PNG_handle_zTXt
#define png_inflate MOZ_PNG_inflate
#define png_info_destroy MOZ_PNG_info_dest
#define png_info_init_3 MOZ_PNG_info_init_3
@@ -497,9 +485,6 @@
#define png_get_next_frame_y_offset MOZ_APNG_get_next_frame_y_offset
#define png_get_num_frames MOZ_APNG_set_num_frames
#define png_get_num_plays MOZ_APNG_set_num_plays
#define png_handle_acTL MOZ_APNG_handle_acTL
#define png_handle_fcTL MOZ_APNG_handle_fcTL
#define png_handle_fdAT MOZ_APNG_handle_fdAT
#define png_have_info MOZ_APNG_have_info
#define png_progressive_read_reset MOZ_APNG_prog_read_reset
#define png_read_frame_head MOZ_APNG_read_frame_head
+33 -30
View File
@@ -1,10 +1,9 @@
/* pngmem.c - stub functions for memory allocation
*
* Last changed in libpng 1.6.26 [October 20, 2016]
* Copyright (c) 2018-2025 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2014,2016 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -47,7 +46,8 @@ png_destroy_png_struct(png_structrp png_ptr)
* have the ability to do that.
*/
PNG_FUNCTION(png_voidp,PNGAPI
png_calloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
png_calloc,(png_const_structrp png_ptr, png_alloc_size_t size),
PNG_ALLOCATED)
{
png_voidp ret;
@@ -73,30 +73,29 @@ png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size),
* to implement a user memory handler. This checks to be sure it isn't
* called with big numbers.
*/
#ifndef PNG_USER_MEM_SUPPORTED
PNG_UNUSED(png_ptr)
#endif
# ifdef PNG_MAX_MALLOC_64K
/* This is support for legacy systems which had segmented addressing
* limiting the maximum allocation size to 65536. It takes precedence
* over PNG_SIZE_MAX which is set to 65535 on true 16-bit systems.
*
* TODO: libpng-1.8: finally remove both cases.
*/
if (size > 65536U) return NULL;
# endif
/* Some compilers complain that this is always true. However, it
* can be false when integer overflow happens.
/* This is checked too because the system malloc call below takes a (size_t).
*/
if (size > 0 && size <= PNG_SIZE_MAX
# ifdef PNG_MAX_MALLOC_64K
&& size <= 65536U
# endif
)
{
#ifdef PNG_USER_MEM_SUPPORTED
if (size > PNG_SIZE_MAX) return NULL;
# ifdef PNG_USER_MEM_SUPPORTED
if (png_ptr != NULL && png_ptr->malloc_fn != NULL)
return png_ptr->malloc_fn(png_constcast(png_structrp,png_ptr), size);
# else
PNG_UNUSED(png_ptr)
# endif
else
#endif
return malloc((size_t)size); /* checked for truncation above */
}
else
return NULL;
/* Use the system malloc */
return malloc((size_t)/*SAFE*/size); /* checked for truncation above */
}
#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) ||\
@@ -120,7 +119,8 @@ png_malloc_array_checked(png_const_structrp png_ptr, int nelements,
PNG_FUNCTION(png_voidp /* PRIVATE */,
png_malloc_array,(png_const_structrp png_ptr, int nelements,
size_t element_size),PNG_ALLOCATED)
size_t element_size),
PNG_ALLOCATED)
{
if (nelements <= 0 || element_size == 0)
png_error(png_ptr, "internal error: array alloc");
@@ -130,7 +130,8 @@ png_malloc_array,(png_const_structrp png_ptr, int nelements,
PNG_FUNCTION(png_voidp /* PRIVATE */,
png_realloc_array,(png_const_structrp png_ptr, png_const_voidp old_array,
int old_elements, int add_elements, size_t element_size),PNG_ALLOCATED)
int old_elements, int add_elements, size_t element_size),
PNG_ALLOCATED)
{
/* These are internal errors: */
if (add_elements <= 0 || element_size == 0 || old_elements < 0 ||
@@ -169,7 +170,8 @@ png_realloc_array,(png_const_structrp png_ptr, png_const_voidp old_array,
* function png_malloc_default is also provided.
*/
PNG_FUNCTION(png_voidp,PNGAPI
png_malloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
png_malloc,(png_const_structrp png_ptr, png_alloc_size_t size),
PNG_ALLOCATED)
{
png_voidp ret;
@@ -243,7 +245,8 @@ png_free(png_const_structrp png_ptr, png_voidp ptr)
}
PNG_FUNCTION(void,PNGAPI
png_free_default,(png_const_structrp png_ptr, png_voidp ptr),PNG_DEPRECATED)
png_free_default,(png_const_structrp png_ptr, png_voidp ptr),
PNG_DEPRECATED)
{
if (png_ptr == NULL || ptr == NULL)
return;
@@ -257,8 +260,8 @@ png_free_default,(png_const_structrp png_ptr, png_voidp ptr),PNG_DEPRECATED)
* of allocating and freeing memory.
*/
void PNGAPI
png_set_mem_fn(png_structrp png_ptr, png_voidp mem_ptr, png_malloc_ptr
malloc_fn, png_free_ptr free_fn)
png_set_mem_fn(png_structrp png_ptr, png_voidp mem_ptr,
png_malloc_ptr malloc_fn, png_free_ptr free_fn)
{
if (png_ptr != NULL)
{
+57 -206
View File
@@ -1,10 +1,9 @@
/* pngpread.c - read a png file in push mode
*
* Last changed in libpng 1.6.24 [August 4, 2016]
* Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
* Copyright (c) 2018-2025 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -32,9 +31,24 @@ if (png_ptr->push_length + 4 > png_ptr->buffer_size) \
if (png_ptr->buffer_size < N) \
{ png_push_save_buffer(png_ptr); return; }
#ifdef PNG_READ_INTERLACING_SUPPORTED
/* Arrays to facilitate interlacing - use pass (0 - 6) as index. */
/* Start of interlace block */
static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */
static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */
static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
/* TODO: Move these arrays to a common utility module to avoid duplication. */
#endif
void PNGAPI
png_process_data(png_structrp png_ptr, png_inforp info_ptr,
png_bytep buffer, png_size_t buffer_size)
png_bytep buffer, size_t buffer_size)
{
if (png_ptr == NULL || info_ptr == NULL)
return;
@@ -47,7 +61,7 @@ png_process_data(png_structrp png_ptr, png_inforp info_ptr,
}
}
png_size_t PNGAPI
size_t PNGAPI
png_process_data_pause(png_structrp png_ptr, int save)
{
if (png_ptr != NULL)
@@ -60,7 +74,7 @@ png_process_data_pause(png_structrp png_ptr, int save)
else
{
/* This includes any pending saved bytes: */
png_size_t remaining = png_ptr->buffer_size;
size_t remaining = png_ptr->buffer_size;
png_ptr->buffer_size = 0;
/* So subtract the saved buffer size, unless all the data
@@ -133,8 +147,8 @@ png_process_some_data(png_structrp png_ptr, png_inforp info_ptr)
void /* PRIVATE */
png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr)
{
png_size_t num_checked = png_ptr->sig_bytes, /* SAFE, does not exceed 8 */
num_to_check = 8 - num_checked;
size_t num_checked = png_ptr->sig_bytes; /* SAFE, does not exceed 8 */
size_t num_to_check = 8 - num_checked;
if (png_ptr->buffer_size < num_to_check)
{
@@ -145,10 +159,10 @@ png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr)
num_to_check);
png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check);
if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check) != 0)
{
if (num_checked < 4 &&
png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4) != 0)
png_error(png_ptr, "Not a PNG file");
else
@@ -179,16 +193,8 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
*/
if ((png_ptr->mode & PNG_HAVE_CHUNK_HEADER) == 0)
{
png_byte chunk_length[4];
png_byte chunk_tag[4];
PNG_PUSH_SAVE_BUFFER_IF_LT(8)
png_push_fill_buffer(png_ptr, chunk_length, 4);
png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
png_reset_crc(png_ptr);
png_crc_read(png_ptr, chunk_tag, 4);
png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
png_check_chunk_name(png_ptr, png_ptr->chunk_name);
png_ptr->push_length = png_read_chunk_header(png_ptr);
png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
}
@@ -212,9 +218,6 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
else if (chunk_name == png_fdAT)
{
PNG_PUSH_SAVE_BUFFER_IF_LT(4)
png_ensure_sequence_number(png_ptr, 4);
if ((png_ptr->mode & PNG_HAVE_fcTL) == 0)
{
/* Discard trailing fdATs for frames other than the first */
@@ -222,13 +225,17 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
png_error(png_ptr, "out of place fdAT");
PNG_PUSH_SAVE_BUFFER_IF_FULL
png_crc_finish(png_ptr, png_ptr->push_length);
png_ensure_sequence_number(png_ptr, png_ptr->push_length);
png_crc_finish(png_ptr, png_ptr->push_length - 4);
png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
}
else
{
/* frame data follows */
PNG_PUSH_SAVE_BUFFER_IF_LT(4)
png_ensure_sequence_number(png_ptr, png_ptr->push_length);
png_ptr->idat_size = png_ptr->push_length - 4;
png_ptr->mode |= PNG_HAVE_IDAT;
png_ptr->process_mode = PNG_READ_IDAT_MODE;
@@ -306,19 +313,27 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
png_benign_error(png_ptr, "Too many IDATs found");
}
else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
/* These flags must be set consistently for all non-IDAT chunks,
* including the unknown chunks.
*/
png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT | PNG_AFTER_IDAT;
}
if (chunk_name == png_IHDR)
{
if (png_ptr->push_length != 13)
png_error(png_ptr, "Invalid IHDR length");
PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);
png_handle_chunk(png_ptr, info_ptr, png_ptr->push_length);
}
else if (chunk_name == png_IEND)
{
PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length);
png_handle_chunk(png_ptr, info_ptr, png_ptr->push_length);
png_ptr->process_mode = PNG_READ_DONE_MODE;
png_push_have_end(png_ptr, info_ptr);
@@ -335,12 +350,6 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
}
#endif
else if (chunk_name == png_PLTE)
{
PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
}
else if (chunk_name == png_IDAT)
{
#ifdef PNG_READ_APNG_SUPPORTED
@@ -356,142 +365,6 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
return;
}
#ifdef PNG_READ_gAMA_SUPPORTED
else if (png_ptr->chunk_name == png_gAMA)
{
PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
#ifdef PNG_READ_sBIT_SUPPORTED
else if (png_ptr->chunk_name == png_sBIT)
{
PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
#ifdef PNG_READ_cHRM_SUPPORTED
else if (png_ptr->chunk_name == png_cHRM)
{
PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
#ifdef PNG_READ_sRGB_SUPPORTED
else if (chunk_name == png_sRGB)
{
PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
#ifdef PNG_READ_iCCP_SUPPORTED
else if (png_ptr->chunk_name == png_iCCP)
{
PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
#ifdef PNG_READ_sPLT_SUPPORTED
else if (chunk_name == png_sPLT)
{
PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
#ifdef PNG_READ_tRNS_SUPPORTED
else if (chunk_name == png_tRNS)
{
PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
#ifdef PNG_READ_bKGD_SUPPORTED
else if (chunk_name == png_bKGD)
{
PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
#ifdef PNG_READ_hIST_SUPPORTED
else if (chunk_name == png_hIST)
{
PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
#ifdef PNG_READ_pHYs_SUPPORTED
else if (chunk_name == png_pHYs)
{
PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
#ifdef PNG_READ_oFFs_SUPPORTED
else if (chunk_name == png_oFFs)
{
PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
#ifdef PNG_READ_pCAL_SUPPORTED
else if (chunk_name == png_pCAL)
{
PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
#ifdef PNG_READ_sCAL_SUPPORTED
else if (chunk_name == png_sCAL)
{
PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
#ifdef PNG_READ_tIME_SUPPORTED
else if (chunk_name == png_tIME)
{
PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
#ifdef PNG_READ_tEXt_SUPPORTED
else if (chunk_name == png_tEXt)
{
PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
#ifdef PNG_READ_zTXt_SUPPORTED
else if (chunk_name == png_zTXt)
{
PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
#ifdef PNG_READ_iTXt_SUPPORTED
else if (chunk_name == png_iTXt)
{
PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
#ifdef PNG_READ_APNG_SUPPORTED
else if (chunk_name == png_acTL)
{
@@ -509,15 +382,14 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
else
{
PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length,
PNG_HANDLE_CHUNK_AS_DEFAULT);
png_handle_chunk(png_ptr, info_ptr, png_ptr->push_length);
}
png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
}
void PNGCBAPI
png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, size_t length)
{
png_bytep ptr;
@@ -527,7 +399,7 @@ png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
ptr = buffer;
if (png_ptr->save_buffer_size != 0)
{
png_size_t save_size;
size_t save_size;
if (length < png_ptr->save_buffer_size)
save_size = length;
@@ -544,7 +416,7 @@ png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
}
if (length != 0 && png_ptr->current_buffer_size != 0)
{
png_size_t save_size;
size_t save_size;
if (length < png_ptr->current_buffer_size)
save_size = length;
@@ -566,7 +438,7 @@ png_push_save_buffer(png_structrp png_ptr)
{
if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
{
png_size_t i, istop;
size_t i, istop;
png_bytep sp;
png_bytep dp;
@@ -581,7 +453,7 @@ png_push_save_buffer(png_structrp png_ptr)
if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
png_ptr->save_buffer_max)
{
png_size_t new_max;
size_t new_max;
png_bytep old_buffer;
if (png_ptr->save_buffer_size > PNG_SIZE_MAX -
@@ -593,7 +465,7 @@ png_push_save_buffer(png_structrp png_ptr)
new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
old_buffer = png_ptr->save_buffer;
png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr,
(png_size_t)new_max);
(size_t)new_max);
if (png_ptr->save_buffer == NULL)
{
@@ -621,7 +493,7 @@ png_push_save_buffer(png_structrp png_ptr)
void /* PRIVATE */
png_push_restore_buffer(png_structrp png_ptr, png_bytep buffer,
png_size_t buffer_length)
size_t buffer_length)
{
png_ptr->current_buffer = buffer;
png_ptr->current_buffer_size = buffer_length;
@@ -700,7 +572,7 @@ png_push_read_IDAT(png_structrp png_ptr)
#ifdef PNG_READ_APNG_SUPPORTED
if (png_ptr->num_frames_read > 0)
{
png_ensure_sequence_number(png_ptr, 4);
png_ensure_sequence_number(png_ptr, png_ptr->push_length);
png_ptr->idat_size -= 4;
}
#endif
@@ -708,7 +580,7 @@ png_push_read_IDAT(png_structrp png_ptr)
if (png_ptr->idat_size != 0 && png_ptr->save_buffer_size != 0)
{
png_size_t save_size = png_ptr->save_buffer_size;
size_t save_size = png_ptr->save_buffer_size;
png_uint_32 idat_size = png_ptr->idat_size;
/* We want the smaller of 'idat_size' and 'current_buffer_size', but they
@@ -718,7 +590,7 @@ png_push_read_IDAT(png_structrp png_ptr)
* will break on either 16-bit or 64-bit platforms.
*/
if (idat_size < save_size)
save_size = (png_size_t)idat_size;
save_size = (size_t)idat_size;
else
idat_size = (png_uint_32)save_size;
@@ -735,7 +607,7 @@ png_push_read_IDAT(png_structrp png_ptr)
if (png_ptr->idat_size != 0 && png_ptr->current_buffer_size != 0)
{
png_size_t save_size = png_ptr->current_buffer_size;
size_t save_size = png_ptr->current_buffer_size;
png_uint_32 idat_size = png_ptr->idat_size;
/* We want the smaller of 'idat_size' and 'current_buffer_size', but they
@@ -744,7 +616,7 @@ png_push_read_IDAT(png_structrp png_ptr)
* larger - this cannot overflow.
*/
if (idat_size < save_size)
save_size = (png_size_t)idat_size;
save_size = (size_t)idat_size;
else
idat_size = (png_uint_32)save_size;
@@ -771,7 +643,7 @@ png_push_read_IDAT(png_structrp png_ptr)
void /* PRIVATE */
png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer,
png_size_t buffer_length)
size_t buffer_length)
{
/* The caller checks for a non-zero buffer length. */
if (!(buffer_length > 0) || buffer == NULL)
@@ -1124,27 +996,6 @@ png_push_process_row(png_structrp png_ptr)
void /* PRIVATE */
png_read_push_finish_row(png_structrp png_ptr)
{
#ifdef PNG_READ_INTERLACING_SUPPORTED
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
static PNG_CONST png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
static PNG_CONST png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */
static PNG_CONST png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */
static PNG_CONST png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
/* Height of interlace block. This is not currently used - if you need
* it, uncomment it here and in png.h
static PNG_CONST png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
*/
#endif
png_ptr->row_number++;
if (png_ptr->row_number < png_ptr->num_rows)
return;
@@ -1257,7 +1108,7 @@ png_voidp PNGAPI
png_get_progressive_ptr(png_const_structrp png_ptr)
{
if (png_ptr == NULL)
return (NULL);
return NULL;
return png_ptr->io_ptr;
}
+969 -595
View File
File diff suppressed because it is too large. Load diff
Loaded 100 of 161 files, more files were not shown because too many files have changed in this diff. Show more