mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
auto merge of #724 : webconv/servo/androidport, r=metajack
Works of android port. Notices. 1. added more native submodules - libpng, libfreetype2, libfontconfig, libexpat (currently, they are on our repo) 2. build directory change : [build directory]/[XXXX] -> [build dir]/[target triples]/[XXXX] 3. added android main 4. uses freeGLUT instead of GLFW on android 4. fixed misc. Usage: configure --target-triples=arm-linux-androideabi && make Result: cross-compiled 32-bit so libraries.
This commit is contained in:
commit
3e36dc3e68
30 changed files with 1245 additions and 132 deletions
12
.gitmodules
vendored
12
.gitmodules
vendored
|
@ -106,3 +106,15 @@
|
|||
[submodule "src/support/png/libpng"]
|
||||
path = src/support/png/libpng
|
||||
url = https://github.com/mozilla-servo/libpng.git
|
||||
[submodule "src/platform/android/fontconfig"]
|
||||
path = src/platform/android/fontconfig
|
||||
url = http://github.com/webconvforge/fontconfig.git
|
||||
[submodule "src/platform/android/libexpat"]
|
||||
path = src/platform/android/libexpat
|
||||
url = http://github.com/webconvforge/libexpat.git
|
||||
[submodule "src/platform/android/libfreetype2"]
|
||||
path = src/platform/android/libfreetype2
|
||||
url = http://github.com/webconvforge/libfreetype2.git
|
||||
[submodule "src/support/glut/rust-glut"]
|
||||
path = src/support/glut/rust-glut
|
||||
url = http://github.com/mozilla-servo/rust-glut.git
|
||||
|
|
49
Makefile.in
49
Makefile.in
|
@ -32,7 +32,7 @@ MKFILE_DEPS := config.stamp $(call rwildcard,$(S)mk/,*)
|
|||
# Enable debug!() etc even without configure --enable-debug
|
||||
# The evaluation of these prints & their arguments is controlled
|
||||
# at runtime by the environment variable RUST_LOG.
|
||||
CFG_RUSTC_FLAGS := $(RUSTFLAGS) --cfg debug
|
||||
CFG_RUSTC_FLAGS += --cfg debug
|
||||
|
||||
ifdef CFG_DISABLE_OPTIMIZE
|
||||
$(info cfg: disabling rustc optimization (CFG_DISABLE_OPTIMIZE))
|
||||
|
@ -55,6 +55,15 @@ export CFG_LOCAL_RUSTC
|
|||
export CFG_ENABLE_DEBUG
|
||||
export RUSTC=$(CFG_RUSTC)
|
||||
export RUSTFLAGS=$(CFG_RUSTC_FLAGS)
|
||||
export CC=$(CFG_CC)
|
||||
export CXX=$(CFG_CXX)
|
||||
export LD=$(CFG_LD)
|
||||
export AR=$(CFG_AR)
|
||||
export RANLIB=$(CFG_RANLIB)
|
||||
export PATH=$(CFG_PATH)
|
||||
export CFG_ANDROID_SDK_PATH
|
||||
export CFG_OSTYPE
|
||||
export CFG_CPUTYPE
|
||||
|
||||
######################################################################
|
||||
# Re-configuration
|
||||
|
@ -83,7 +92,7 @@ $(S)config.stamp : $(S)configure $(S)Makefile.in
|
|||
ifneq ($(CFG_LOCAL_RUSTC),1)
|
||||
$(CFG_RUSTC):
|
||||
@$(call E, building rustc)
|
||||
$(Q)$(MAKE) -C "$(CFG_BUILD_DIR)src/compiler/rust" CFG_RUSTC_FLAGS="" RUSTFLAGS=""
|
||||
$(Q)$(MAKE) -C "$(CFG_BUILD_DIR)src/compiler/rust" CFG_RUSTC_FLAGS="" RUSTFLAGS="" CC=gcc CXX=g++ LD=ld AR=ar
|
||||
|
||||
clean-rust:
|
||||
@$(call E, cleaning rustc)
|
||||
|
@ -96,7 +105,7 @@ clean-rust:
|
|||
|
||||
endif
|
||||
|
||||
src/compiler/rust/rust-auto-clean-stamp: $(S)src/compiler/rust-auto-clean-trigger
|
||||
$(B)/src/compiler/rust/rust-auto-clean-stamp: $(S)src/compiler/rust-auto-clean-trigger
|
||||
$(Q)$(MAKE) clean-rust
|
||||
touch $@
|
||||
|
||||
|
@ -126,6 +135,8 @@ endif
|
|||
# their name already, while others don't.
|
||||
DONE_$(1) = $$(B)src/$$(PATH_$(1))/lib*.dummy
|
||||
DEPS_SUBMODULES += $$(PATH_$(1))
|
||||
DEPS_SUBMODULES += $$(PATH_$(1))/.libs
|
||||
DEPS_SUBMODULES += $$(PATH_$(1))/src/.libs
|
||||
endef
|
||||
|
||||
# these will get populated.
|
||||
|
@ -140,7 +151,7 @@ include $(S)mk/sub.mk
|
|||
# Define how to make submodule targets
|
||||
define DEF_SUBMODULE_RULES
|
||||
|
||||
ENV_RLDFLAGS_$(1) = $$(foreach dep,$$(DEPS_$(1)),-L $$(B)src/$$(PATH_$$(dep)))
|
||||
ENV_RLDFLAGS_$(1) = $$(foreach dep,$$(DEPS_$(1)),-L $$(B)src/$$(PATH_$$(dep)) -L $$(B)src/$$(PATH_$$(dep))/.libs -L $$(B)src/$$(PATH_$$(dep))/src/.libs)
|
||||
|
||||
# variables that depend on dependency definitions from sub.mk!
|
||||
ENV_CFLAGS_$(1) = CFLAGS="$$(CFLAGS_$(1))"
|
||||
|
@ -164,10 +175,12 @@ $$(DONE_$(1)) : $$(DONE_DEPS_$(1)) $$(ROUGH_DEPS_$(1)) $$(RUSTC_DEP_$(1))
|
|||
# @$$(call E, $(1) deps= $$(DEPS_$(1)))
|
||||
# @$$(call E, $(1) done_deps= $$(DONE_DEPS_$(1)))
|
||||
# @$$(call E, $(1) cflags= $$(ENV_CFLAGS_$(1)))
|
||||
# @$$(call E, $(1) cxxflags= $$(ENV_CXXFLAGS_$(1)))
|
||||
# @$$(call E, $(1) rflags= $$(ENV_RFLAGS_$(1)))
|
||||
|
||||
$$(Q) \
|
||||
$$(ENV_CFLAGS_$(1)) \
|
||||
$$(ENV_CXXFLAGS_$(1)) \
|
||||
$$(ENV_RFLAGS_$(1)) \
|
||||
$$(MAKE) -C $$(B)src/$$(PATH_$(1)) && touch $$(DONE_$(1))
|
||||
|
||||
|
@ -232,29 +245,29 @@ include $(S)mk/clean.mk
|
|||
|
||||
.DEFAULT_GOAL := all
|
||||
.PHONY: all
|
||||
all: src/compiler/rust/rust-auto-clean-stamp servo package
|
||||
all: $(B)/src/compiler/rust/rust-auto-clean-stamp servo package
|
||||
|
||||
# Servo helper libraries
|
||||
|
||||
$(DONE_util): $(DEPS_util)
|
||||
@$(call E, compile: $@)
|
||||
$(Q)$(RUSTC) $(RFLAGS_util) --out-dir src/components/util $< && touch $@
|
||||
$(Q)$(RUSTC) $(RFLAGS_util) --out-dir $(B)src/components/util $< && touch $@
|
||||
|
||||
$(DONE_net): $(DEPS_net)
|
||||
@$(call E, compile: $@)
|
||||
$(Q)$(RUSTC) $(RFLAGS_net) --out-dir src/components/net $< && touch $@
|
||||
$(Q)$(RUSTC) $(RFLAGS_net) --out-dir $(B)src/components/net $< && touch $@
|
||||
|
||||
$(DONE_msg): $(DEPS_msg)
|
||||
@$(call E, compile: $@)
|
||||
$(Q)$(RUSTC) $(RFLAGS_msg) --out-dir src/components/msg $< && touch $@
|
||||
$(Q)$(RUSTC) $(RFLAGS_msg) --out-dir $(B)src/components/msg $< && touch $@
|
||||
|
||||
$(DONE_gfx): $(DEPS_gfx)
|
||||
@$(call E, compile: $@)
|
||||
$(Q)$(RUSTC) $(RFLAGS_gfx) --out-dir src/components/gfx $< && touch $@
|
||||
$(Q)$(RUSTC) $(RFLAGS_gfx) --out-dir $(B)src/components/gfx $< && touch $@
|
||||
|
||||
$(DONE_script): $(DEPS_script)
|
||||
@$(call E, compile: $@)
|
||||
$(Q)$(RUSTC) $(RFLAGS_script) --out-dir src/components/script $< && touch $@
|
||||
$(Q)$(RUSTC) $(RFLAGS_script) --out-dir $(B)src/components/script $< && touch $@
|
||||
|
||||
BINDINGS_SRC = $(S)/src/components/script/dom/bindings/codegen
|
||||
|
||||
|
@ -289,21 +302,27 @@ $(BINDINGS_SRC)/ParserResults.pkl: $(globalgen_dependencies) \
|
|||
|
||||
# Servo binaries
|
||||
|
||||
ifneq ($(CFG_OSTYPE),linux-androideabi)
|
||||
servo: $(DEPS_servo)
|
||||
@$(call E, compile: $@)
|
||||
$(Q)$(RUSTC) $(RFLAGS_servo) -o $@ $< --bin
|
||||
else
|
||||
servo: $(DEPS_servo)
|
||||
@$(call E, compile: $@)
|
||||
$(Q)$(RUSTC) $(RFLAGS_servo) -o $@ $< --lib
|
||||
endif
|
||||
|
||||
# Darwin app packaging
|
||||
|
||||
ifeq ($(OSTYPE),apple-darwin)
|
||||
ifeq ($(CFG_OSTYPE),apple-darwin)
|
||||
|
||||
package: servo
|
||||
mkdir -p Servo.app/Contents/MacOS/src/platform/macos/rust-cocoa
|
||||
mkdir -p Servo.app/Contents/MacOS/src/platform/macos/rust-azure
|
||||
cp $(S)/Info.plist Servo.app/Contents/
|
||||
mkdir -p Servo.app/Contents/MacOS/src/support/azure/rust-azure
|
||||
cp $(S)Info.plist Servo.app/Contents/
|
||||
cp servo Servo.app/Contents/MacOS/
|
||||
cp src/platform/macos/rust-cocoa/lib*.dylib Servo.app/Contents/MacOS/src/platform/macos/rust-cocoa/
|
||||
cp src/platform/macos/rust-azure/lib*.dylib Servo.app/Contents/MacOS/src/platform/macos/rust-azure/
|
||||
cp $(B)src/platform/macos/rust-cocoa/lib*.dylib Servo.app/Contents/MacOS/src/platform/macos/rust-cocoa/
|
||||
cp $(B)src/support/azure/rust-azure/lib*.dylib Servo.app/Contents/MacOS/src/support/azure/rust-azure/
|
||||
|
||||
else
|
||||
|
||||
|
|
347
configure
vendored
347
configure
vendored
|
@ -182,6 +182,82 @@ opt() {
|
|||
fi
|
||||
}
|
||||
|
||||
split_triple() {
|
||||
local TRIPLE=$1
|
||||
local ARCH=$2
|
||||
local VENDOR=$3
|
||||
local OS=$4
|
||||
|
||||
eval $ARCH=$(echo "$TRIPLE" | cut -d'-' -f1)
|
||||
eval $VENDOR=$(echo "$TRIPLE" | cut -d'-' -f2)
|
||||
eval $OS=$(echo "$TRIPLE" | cut -d'-' -f3)
|
||||
|
||||
if [ $(echo "$TRIPLE" | cut -d'-' -f3) = "androideabi" ]
|
||||
then
|
||||
eval $OS="android"
|
||||
fi
|
||||
}
|
||||
|
||||
os_type() {
|
||||
# The goal here is to come up with the same triple as LLVM would,
|
||||
# at least for the subset of platforms we're willing to target.
|
||||
|
||||
local OP=$1
|
||||
local OSTYPE=$(echo "$2" | tr '[:upper:]' '[:lower:]')
|
||||
local V="${OP}"
|
||||
|
||||
case $OSTYPE in
|
||||
|
||||
linux)
|
||||
eval $V=unknown-linux-gnu
|
||||
;;
|
||||
|
||||
freebsd)
|
||||
eval $V=unknown-freebsd
|
||||
;;
|
||||
|
||||
darwin)
|
||||
eval $V=apple-darwin
|
||||
;;
|
||||
|
||||
mingw32*)
|
||||
eval $V=pc-mingw32
|
||||
;;
|
||||
|
||||
android)
|
||||
eval $V=linux-androideabi
|
||||
;;
|
||||
|
||||
*)
|
||||
err "unknown OS type: $OSTYPE"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
cpu_type() {
|
||||
local OP=$1
|
||||
local CPUTYPE=$2
|
||||
local V="${OP}"
|
||||
|
||||
case $CPUTYPE in
|
||||
|
||||
i386 | i486 | i686 | i786 | x86)
|
||||
eval $V=i686
|
||||
;;
|
||||
|
||||
xscale | arm)
|
||||
eval $V=arm
|
||||
;;
|
||||
|
||||
x86_64 | x86-64 | x64 | amd64)
|
||||
eval $V=x86_64
|
||||
;;
|
||||
|
||||
*)
|
||||
err "unknown CPU type: $CPUTYPE"
|
||||
esac
|
||||
}
|
||||
|
||||
msg "looking for configure programs"
|
||||
need_cmd cmp
|
||||
need_cmd mkdir
|
||||
|
@ -198,70 +274,29 @@ need_cmd sed
|
|||
|
||||
msg "inspecting environment"
|
||||
|
||||
CFG_OSTYPE=$(uname -s)
|
||||
CFG_CPUTYPE=$(uname -m)
|
||||
OSTYPE=$(uname -s)
|
||||
CPUTYPE=$(uname -m)
|
||||
|
||||
if [ $CFG_OSTYPE = Darwin -a $CFG_CPUTYPE = i386 ]
|
||||
if [ $OSTYPE = Darwin -a $CPUTYPE = i386 ]
|
||||
then
|
||||
# Darwin's `uname -m` lies and always returns i386. We have to use sysctl
|
||||
# instead.
|
||||
if sysctl hw.optional.x86_64 | grep -q ': 1'
|
||||
then
|
||||
CFG_CPUTYPE=x86_64
|
||||
CPUTYPE=x86_64
|
||||
fi
|
||||
fi
|
||||
|
||||
# The goal here is to come up with the same triple as LLVM would,
|
||||
# at least for the subset of platforms we're willing to target.
|
||||
os_type CFG_BUILD_OSTYPE ${OSTYPE}
|
||||
cpu_type CFG_BUILD_CPUTYPE ${CPUTYPE}
|
||||
|
||||
case $CFG_OSTYPE in
|
||||
|
||||
Linux)
|
||||
CFG_OSTYPE=unknown-linux-gnu
|
||||
;;
|
||||
|
||||
FreeBSD)
|
||||
CFG_OSTYPE=unknown-freebsd
|
||||
;;
|
||||
|
||||
Darwin)
|
||||
CFG_OSTYPE=apple-darwin
|
||||
;;
|
||||
|
||||
MINGW32*)
|
||||
CFG_OSTYPE=pc-mingw32
|
||||
;;
|
||||
|
||||
*)
|
||||
err "unknown OS type: $CFG_OSTYPE"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
case $CFG_CPUTYPE in
|
||||
|
||||
i386 | i486 | i686 | i786 | x86)
|
||||
CFG_CPUTYPE=i686
|
||||
;;
|
||||
|
||||
xscale | arm)
|
||||
CFG_CPUTYPE=arm
|
||||
;;
|
||||
|
||||
x86_64 | x86-64 | x64 | amd64)
|
||||
CFG_CPUTYPE=x86_64
|
||||
;;
|
||||
|
||||
*)
|
||||
err "unknown CPU type: $CFG_CPUTYPE"
|
||||
esac
|
||||
|
||||
DEFAULT_HOST_TRIPLE="${CFG_CPUTYPE}-${CFG_OSTYPE}"
|
||||
DEFAULT_TARGET_TRIPLE="${CFG_BUILD_CPUTYPE}-${CFG_BUILD_OSTYPE}"
|
||||
|
||||
CFG_SRC_DIR="$(cd $(dirname $0) && pwd)/"
|
||||
CFG_BUILD_DIR="$(pwd)/"
|
||||
CFG_BUILD_HOME="$(pwd)/"
|
||||
CFG_SELF=${CFG_SRC_DIR}$(basename $0)
|
||||
CFG_CONFIGURE_ARGS="$@"
|
||||
CFG_PATH=$PATH
|
||||
|
||||
OPTIONS=""
|
||||
HELP=0
|
||||
|
@ -287,6 +322,12 @@ opt manage-submodules 1 "let the build manage the git submodules"
|
|||
opt fast-make 0 "use .gitmodules as timestamp for submodule deps"
|
||||
opt debug 0 "use debugging symbols"
|
||||
valopt local-rust-root "" "set prefix for local rust binary"
|
||||
valopt target-triples "${DEFAULT_TARGET_TRIPLE}" "target triple to be compiled"
|
||||
valopt android-cross-path "/opt/ndk_standalone" "Android NDK cross compiler path"
|
||||
valopt android-ndk-path "/opt/android-ndk" "Android NDK path"
|
||||
valopt android-sdk-path "/opt/android-sdk" "Android SDK path"
|
||||
valopt android-font-path "/system/fonts" "Android Font path"
|
||||
valopt android-resource-path "/sdcard/servo" "Android Resource path"
|
||||
|
||||
if [ $HELP -eq 1 ]
|
||||
then
|
||||
|
@ -294,18 +335,47 @@ then
|
|||
exit 0
|
||||
fi
|
||||
|
||||
# Split target triple
|
||||
split_triple "${CFG_TARGET_TRIPLES}" TARGET_CPUTYPE TARGET_VENDOR TARGET_OSTYPE
|
||||
# Set target os and cpu type
|
||||
os_type CFG_OSTYPE ${TARGET_OSTYPE}
|
||||
cpu_type CFG_CPUTYPE ${TARGET_CPUTYPE}
|
||||
|
||||
step_msg "looking for build programs"
|
||||
case ${TARGET_OSTYPE} in
|
||||
android)
|
||||
CFG_PATH="${CFG_ANDROID_CROSS_PATH}/bin":$PATH
|
||||
export PATH=${CFG_PATH}
|
||||
|
||||
probe CFG_CC arm-linux-androideabi-gcc
|
||||
probe CFG_CXX arm-linux-androideabi-g++
|
||||
probe CFG_LD arm-linux-androideabi-ld
|
||||
probe CFG_AR arm-linux-androideabi-ar
|
||||
probe CFG_RANLIB arm-linux-androideabi-ranlib
|
||||
CFG_RUSTC_FLAGS="--target=${CFG_TARGET_TRIPLES} --android-cross-path=${CFG_ANDROID_CROSS_PATH}"
|
||||
;;
|
||||
*)
|
||||
CFG_PATH=$PATH
|
||||
probe CFG_CC gcc
|
||||
probe CFG_CXX g++
|
||||
probe CFG_LD ld
|
||||
probe CFG_AR ar
|
||||
probe CFG_RANLIB ranlib
|
||||
CFG_RUSTC_FLAGS=""
|
||||
;;
|
||||
esac
|
||||
|
||||
probe_need CFG_GIT git
|
||||
probe_need CFG_PYTHON2 python2 python2.7 python
|
||||
probe CFG_CLANG clang++
|
||||
probe CFG_GCC gcc
|
||||
probe CFG_LD ld
|
||||
# Spidermonkey requires autoconf 2.13 exactly
|
||||
probe_need CFG_AUTOCONF213 autoconf213 \
|
||||
autoconf2.13 \
|
||||
autoconf-2.13
|
||||
|
||||
CFG_BUILD_DIR="${CFG_BUILD_HOME}${CFG_TARGET_TRIPLES}/"
|
||||
make_dir "${CFG_BUILD_DIR}"
|
||||
|
||||
if [ ! -z "$CFG_LOCAL_RUST_ROOT" ]
|
||||
then
|
||||
if [ -f ${CFG_LOCAL_RUST_ROOT}/bin/rustc ]
|
||||
|
@ -313,6 +383,7 @@ then
|
|||
LRV=`${CFG_LOCAL_RUST_ROOT}/bin/rustc --version`
|
||||
step_msg "using rustc at: ${CFG_LOCAL_RUST_ROOT} with version: $LRV"
|
||||
CFG_RUSTC=${CFG_LOCAL_RUST_ROOT}/bin/rustc
|
||||
CFG_RUST_HOME=${CFG_LOCAL_RUST_ROOT}
|
||||
CFG_LOCAL_RUSTC=1
|
||||
else
|
||||
err "No rustc found at ${CFG_LOCAL_RUST_ROOT}/bin/rustc"
|
||||
|
@ -320,10 +391,11 @@ then
|
|||
else
|
||||
step_msg "using in-tree rust compiler"
|
||||
# The Rust compiler we're going to build
|
||||
CFG_RUSTC="${CFG_BUILD_DIR}src/compiler/rust/${DEFAULT_HOST_TRIPLE}/stage2/bin/rustc"
|
||||
CFG_RUSTC="${CFG_BUILD_DIR}src/compiler/rust/${DEFAULT_TARGET_TRIPLE}/stage2/bin/rustc"
|
||||
CFG_RUST_HOME="${CFG_BUILD_DIR}src/compiler/rust/${DEFAULT_TARGET_TRIPLE}/stage2"
|
||||
fi
|
||||
|
||||
if [ -z "$CFG_ENABLE_CLANG" -a -z "$CFG_GCC" ]
|
||||
if [ -z "$CFG_ENABLE_CLANG" -a -z "$CFG_CC" ]
|
||||
then
|
||||
err "either clang or gcc is required"
|
||||
fi
|
||||
|
@ -372,7 +444,11 @@ msg "configuring src/mozjs"
|
|||
AUTOCONF213_M4_MACROS="$(dirname ${CFG_AUTOCONF213})/../share/$(basename ${CFG_AUTOCONF213})/"
|
||||
# Run the SpiderMonkey autoconf using autoconf 2.13
|
||||
(cd ${CFG_SRC_DIR}src/support/spidermonkey/mozjs/js/src && "${CFG_AUTOCONF213}" -l "${AUTOCONF213_M4_MACROS}") || exit $?
|
||||
|
||||
if [ $CFG_OSTYPE = "linux-androideabi" ]
|
||||
then
|
||||
msg "configuring src/libexpat"
|
||||
(cd ${CFG_SRC_DIR}src/platform/android/libexpat/expat && sh "buildconf.sh") || exit $?
|
||||
fi
|
||||
# Pixman and cairo require some care to autoconf correctly for our in-tree build.
|
||||
# The normal autogen.sh files mostly just run autoreconfig but we need more fine control
|
||||
|
||||
|
@ -403,8 +479,6 @@ CFG_SUBMODULES="\
|
|||
support/css/rust-css \
|
||||
support/css/rust-cssparser \
|
||||
support/geom/rust-geom \
|
||||
support/glfw/glfw \
|
||||
support/glfw/glfw-rs \
|
||||
support/harfbuzz/rust-harfbuzz \
|
||||
support/hubbub/libhubbub \
|
||||
support/hubbub/rust-hubbub \
|
||||
|
@ -428,6 +502,8 @@ CFG_SUBMODULES="\
|
|||
if [ $CFG_OSTYPE = "apple-darwin" ]
|
||||
then
|
||||
CFG_SUBMODULES="\
|
||||
support/glfw/glfw \
|
||||
support/glfw/glfw-rs \
|
||||
platform/macos/rust-cocoa \
|
||||
platform/macos/rust-core-foundation \
|
||||
platform/macos/rust-core-graphics \
|
||||
|
@ -439,12 +515,54 @@ fi
|
|||
if [ $CFG_OSTYPE = "unknown-linux-gnu" ]
|
||||
then
|
||||
CFG_SUBMODULES="\
|
||||
support/glfw/glfw \
|
||||
support/glfw/glfw-rs \
|
||||
platform/linux/rust-fontconfig \
|
||||
platform/linux/rust-freetype \
|
||||
platform/linux/rust-xlib \
|
||||
${CFG_SUBMODULES}"
|
||||
fi
|
||||
|
||||
if [ $CFG_OSTYPE = "linux-androideabi" ]
|
||||
then
|
||||
CFG_SUBMODULES="\
|
||||
support/glut/rust-glut \
|
||||
platform/android/libexpat \
|
||||
platform/android/libfreetype2 \
|
||||
platform/android/fontconfig \
|
||||
platform/linux/rust-fontconfig \
|
||||
platform/linux/rust-freetype \
|
||||
${CFG_SUBMODULES}"
|
||||
fi
|
||||
|
||||
step_msg "writing configuration"
|
||||
|
||||
putvar CFG_TARGET_TRIPLES
|
||||
putvar CFG_CPUTYPE
|
||||
putvar CFG_OSTYPE
|
||||
putvar CFG_SRC_DIR
|
||||
putvar CFG_BUILD_HOME
|
||||
putvar CFG_BUILD_DIR
|
||||
putvar CFG_CONFIGURE_ARGS
|
||||
putvar CFG_SUBMODULES
|
||||
putvar CFG_DISABLE_MANAGE_SUBMODULES
|
||||
putvar CFG_RUSTC
|
||||
putvar CFG_RUSTC_FLAGS
|
||||
putvar CFG_RUST_HOME
|
||||
putvar CFG_PATH
|
||||
putvar CFG_LOCAL_RUSTC
|
||||
putvar CFG_LOCAL_RUST_ROOT
|
||||
putvar CFG_ENABLE_DEBUG
|
||||
|
||||
msg
|
||||
copy_if_changed ${CFG_SRC_DIR}Makefile.in ${CFG_BUILD_HOME}Makefile
|
||||
move_if_changed ${CFG_SRC_DIR}config.tmp ${CFG_SRC_DIR}config.mk
|
||||
copy_if_changed ${CFG_SRC_DIR}config.mk ${CFG_BUILD_HOME}config.mk
|
||||
rm -f ${CFG_SRC_DIR}config.tmp
|
||||
touch ${CFG_SRC_DIR}config.stamp
|
||||
|
||||
export CFG_CONFIG_MK="${CFG_BUILD_HOME}config.mk"
|
||||
|
||||
step_msg "making build directories"
|
||||
|
||||
cd "${CFG_BUILD_DIR}"
|
||||
|
@ -484,14 +602,28 @@ done
|
|||
if [ ${do_reconfigure} -ne 0 ]
|
||||
then
|
||||
cd ${CFG_BUILD_DIR}src/compiler/rust
|
||||
${CFG_SRC_DIR}src/compiler/rust/configure
|
||||
RUST_CONFIGURE_ARGS=""
|
||||
if [ $CFG_OSTYPE = "linux-androideabi" ]; then
|
||||
RUST_CONFIGURE_ARGS="--target-triples=arm-linux-androideabi --android-cross-path=${CFG_ANDROID_CROSS_PATH}"
|
||||
fi
|
||||
${CFG_SRC_DIR}src/compiler/rust/configure ${RUST_CONFIGURE_ARGS}
|
||||
cd ${CFG_BUILD_DIR}
|
||||
fi
|
||||
|
||||
#fontconfig expects to use an installed freetype, but we want to override that behavior to use our version
|
||||
if [ $CFG_OSTYPE = "linux-androideabi" ]
|
||||
then
|
||||
export FREETYPE_CFLAGS="-I${CFG_SRC_DIR}src/platform/android/libfreetype2/include -I${CFG_BUILD_DIR}src/platform/android/libfreetype2/include"
|
||||
export FREETYPE_LIBS="-L${CFG_BUILD_DIR}src/platform/android/libfreetype2/.libs -lfreetype"
|
||||
fi
|
||||
|
||||
# PIC all the things
|
||||
export CFLAGS="${CFLAGS} -fPIC"
|
||||
export LDFLAGS="${CFLAGS} -fPIC"
|
||||
|
||||
# cross compile configurations
|
||||
EXTRA_CONFIGURE_ARGS="CC=${CFG_CC} CXX=${CFG_CXX} LD=${CFG_LD} AR=${CFG_AR} RANLIB=${CFG_RANLIB}"
|
||||
|
||||
for i in ${CFG_SUBMODULES}
|
||||
do
|
||||
if [ -d ${CFG_BUILD_DIR}src/${i} ]
|
||||
|
@ -499,25 +631,69 @@ do
|
|||
cd ${CFG_BUILD_DIR}src/${i}
|
||||
fi
|
||||
CONFIGURE_SCRIPT="${CFG_SRC_DIR}src/${i}/configure"
|
||||
# needed because Spidermonkey configure is in non-standard location
|
||||
if [ $i = "support/spidermonkey/mozjs" ]; then
|
||||
CONFIGURE_SCRIPT="${CFG_SRC_DIR}src/${i}/js/src/configure"
|
||||
CONFIGURE_ARGS=""
|
||||
ENV_VARS=""
|
||||
|
||||
if [ ! -z $CFG_ENABLE_DEBUG ]; then
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS} --enable-debug"
|
||||
fi
|
||||
|
||||
# needed because Azure's configure wants "--enable-skia"
|
||||
CONFIGURE_ARGS=""
|
||||
ENV_VARS=""
|
||||
if [ $i = "support/azure/rust-azure" ]; then
|
||||
CONFIGURE_ARGS="--enable-skia"
|
||||
fi
|
||||
if [ $i = "support/nss/nspr" ]; then
|
||||
CONFIGURE_ARGS="--enable-64bit"
|
||||
fi
|
||||
if [ $i = "support/spidermonkey/mozjs" ]; then
|
||||
if [ ! -z $CFG_ENABLE_DEBUG ]; then
|
||||
CONFIGURE_ARGS="--enable-debug"
|
||||
fi
|
||||
fi
|
||||
case $i in
|
||||
support/nss/nspr)
|
||||
if [ ${CFG_OSTYPE} = "linux-androideabi" ]; then
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS} --target=arm-linux-androideabi"
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS} --with-android-ndk=${CFG_ANDROID_NDK_PATH}"
|
||||
else
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS} --enable-64bit"
|
||||
fi
|
||||
;;
|
||||
support/nss/nss)
|
||||
if [ ${CFG_OSTYPE} = "linux-androideabi" ]; then
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS} --host=arm-linux-androideabi"
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS} --android-ndk-path=${CFG_ANDROID_NDK_PATH}"
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS} --android-api-version=14"
|
||||
fi
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS}"
|
||||
;;
|
||||
platform/android/libexpat)
|
||||
CONFIGURE_SCRIPT="${CFG_SRC_DIR}src/${i}/expat/configure"
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS} --host=arm-linux-androideabi"
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS} --with-sysroot=${CFG_ANDROID_CROSS_PATH}/sysroot"
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS}"
|
||||
;;
|
||||
platform/android/libfreetype2)
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS} --host=arm-linux"
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS} --with-sysroot=${CFG_ANDROID_CROSS_PATH}/sysroot"
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS} --without-zlib"
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS}"
|
||||
;;
|
||||
platform/android/fontconfig)
|
||||
CONFIGURE_SCRIPT="${CFG_SRC_DIR}src/${i}/autogen.sh"
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS} --host=arm-linux-androideabi"
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS} --with-arch=arm"
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS} --with-expat-includes=${CFG_SRC_DIR}src/platform/android/libexpat/expat/lib"
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS} --with-expat-lib=${CFG_BUILD_DIR}src/platform/android/libexpat/.libs"
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS} --with-sysroot=${CFG_ANDROID_CROSS_PATH}/sysroot"
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS} --with-cache-dir=${CFG_ANDROID_RESOURCE_PATH}/.fccache"
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS} --with-confdir=${CFG_ANDROID_RESOURCE_PATH}/.fcconfig"
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS} --with-default-fonts=${CFG_ANDROID_FONT_PATH}"
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS}"
|
||||
;;
|
||||
support/spidermonkey/mozjs)
|
||||
# needed because Spidermonkey configure is in non-standard location
|
||||
CONFIGURE_SCRIPT="${CFG_SRC_DIR}src/${i}/js/src/configure"
|
||||
if [ ${CFG_OSTYPE} = "linux-androideabi" ]; then
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS} --target=arm-linux-androideabi"
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS} --with-android-ndk=${CFG_ANDROID_NDK_PATH}"
|
||||
fi
|
||||
;;
|
||||
support/azure/rust-azure)
|
||||
# needed because Azure's configure wants "--enable-skia"
|
||||
CONFIGURE_ARGS="${CONFIGURE_ARGS} --enable-skia"
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -f ${CONFIGURE_SCRIPT} ]
|
||||
then
|
||||
|
@ -525,25 +701,4 @@ do
|
|||
fi
|
||||
done
|
||||
|
||||
step_msg "writing configuration"
|
||||
|
||||
putvar DEFAULT_HOST_TRIPLE
|
||||
putvar CFG_CPUTYPE
|
||||
putvar CFG_OSTYPE
|
||||
putvar CFG_SRC_DIR
|
||||
putvar CFG_BUILD_DIR
|
||||
putvar CFG_CONFIGURE_ARGS
|
||||
putvar CFG_SUBMODULES
|
||||
putvar CFG_DISABLE_MANAGE_SUBMODULES
|
||||
putvar CFG_RUSTC
|
||||
putvar CFG_LOCAL_RUSTC
|
||||
putvar CFG_ENABLE_DEBUG
|
||||
|
||||
msg
|
||||
copy_if_changed ${CFG_SRC_DIR}Makefile.in ${CFG_BUILD_DIR}Makefile
|
||||
move_if_changed ${CFG_SRC_DIR}config.tmp ${CFG_SRC_DIR}config.mk
|
||||
copy_if_changed ${CFG_SRC_DIR}config.mk ${CFG_BUILD_DIR}config.mk
|
||||
rm -f ${CFG_SRC_DIR}config.tmp
|
||||
touch ${CFG_SRC_DIR}config.stamp
|
||||
|
||||
step_msg "complete"
|
||||
|
|
|
@ -6,6 +6,7 @@ check-$(1) : $$(DONE_$(1))
|
|||
|
||||
$$(Q) \
|
||||
$$(ENV_CFLAGS_$(1)) \
|
||||
$$(ENV_CXXFLAGS_$(1)) \
|
||||
$$(ENV_RFLAGS_$(1)) \
|
||||
$$(MAKE) -C $$(B)src/$$(PATH_$(1)) check
|
||||
|
||||
|
|
|
@ -47,4 +47,4 @@ clean-script:
|
|||
|
||||
clean-servo: clean-gfx clean-util clean-net clean-script clean-msg
|
||||
@$(call E, "cleaning servo")
|
||||
$(Q)rm -f servo servo-test
|
||||
$(Q)rm -f servo servo-test libservo*.so
|
||||
|
|
48
mk/sub.mk
48
mk/sub.mk
|
@ -157,3 +157,51 @@ DEPS_rust-layers += \
|
|||
$(NULL)
|
||||
endif
|
||||
|
||||
ifeq ($(CFG_OSTYPE),linux-androideabi)
|
||||
DEPS_rust-azure += \
|
||||
rust-freetype \
|
||||
rust-fontconfig \
|
||||
fontconfig \
|
||||
libfreetype2 \
|
||||
libexpat \
|
||||
$(NULL)
|
||||
|
||||
# See note at top of file
|
||||
DEPS_rust-layers += \
|
||||
rust-freetype \
|
||||
rust-fontconfig \
|
||||
$(NULL)
|
||||
|
||||
DEPS_rust-fontconfig += \
|
||||
fontconfig \
|
||||
rust-freetype \
|
||||
$(NULL)
|
||||
|
||||
DEPS_rust-freetype += \
|
||||
libfreetype2 \
|
||||
$(NULL)
|
||||
|
||||
DEPS_fontconfig += \
|
||||
libexpat \
|
||||
libfreetype2 \
|
||||
$(NULL)
|
||||
|
||||
CFLAGS_fontconfig += \
|
||||
"-I$(S)src/platform/android/libexpat/expat/lib" \
|
||||
"-I$(S)src/platform/android/libfreetype2/include" \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
DEPS_skia += \
|
||||
libfreetype2 \
|
||||
$(NULL)
|
||||
|
||||
CXXFLAGS_skia += \
|
||||
-I$(S)src/platform/android/libfreetype2/include \
|
||||
$(NULL)
|
||||
|
||||
NATIVE_BUILD += \
|
||||
libfreetype2 \
|
||||
libexpat \
|
||||
fontconfig \
|
||||
$(NULL)
|
||||
|
|
|
@ -353,6 +353,7 @@ impl Font {
|
|||
}
|
||||
|
||||
#[cfg(target_os="linux")]
|
||||
#[cfg(target_os="android")]
|
||||
fn create_azure_font(&self) -> ScaledFont {
|
||||
let freetype_font = self.handle.face;
|
||||
let size = self.style.pt_size as AzFloat;
|
||||
|
|
|
@ -20,9 +20,9 @@ extern mod servo_msg (name = "msg");
|
|||
// shapers. For now, however, this is a hard dependency.
|
||||
extern mod harfbuzz;
|
||||
|
||||
// Linux-specific library dependencies
|
||||
#[cfg(target_os="linux")] extern mod fontconfig;
|
||||
#[cfg(target_os="linux")] extern mod freetype;
|
||||
// Linux and Android-specific library dependencies
|
||||
#[cfg(target_os="linux")] #[cfg(target_os="android")] extern mod fontconfig;
|
||||
#[cfg(target_os="linux")] #[cfg(target_os="android")] extern mod freetype;
|
||||
|
||||
// Mac OS-specific library dependencies
|
||||
#[cfg(target_os="macos")] extern mod core_foundation;
|
||||
|
|
331
src/components/gfx/platform/android/font.rs
Normal file
331
src/components/gfx/platform/android/font.rs
Normal file
|
@ -0,0 +1,331 @@
|
|||
/* 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/. */
|
||||
|
||||
extern mod freetype;
|
||||
|
||||
use font::{CSSFontWeight, FontHandleMethods, FontMetrics, FontTableMethods};
|
||||
use font::{FontTableTag, FractionalPixel, SpecifiedFontStyle, UsedFontStyle, FontWeight100};
|
||||
use font::{FontWeight200, FontWeight300, FontWeight400, FontWeight500, FontWeight600};
|
||||
use font::{FontWeight700, FontWeight800, FontWeight900};
|
||||
use geometry::Au;
|
||||
use geometry;
|
||||
use platform::font_context::FontContextHandle;
|
||||
use text::glyph::GlyphIndex;
|
||||
use text::util::{float_to_fixed, fixed_to_float};
|
||||
|
||||
use freetype::freetype::{FT_Get_Char_Index, FT_Get_Postscript_Name};
|
||||
use freetype::freetype::{FT_Load_Glyph, FT_Set_Char_Size};
|
||||
use freetype::freetype::{FT_New_Face, FT_Get_Sfnt_Table};
|
||||
use freetype::freetype::{FT_New_Memory_Face, FT_Done_Face};
|
||||
use freetype::freetype::{FTErrorMethods, FT_F26Dot6, FT_Face, FT_FaceRec};
|
||||
use freetype::freetype::{FT_GlyphSlot, FT_Library, FT_Long, FT_ULong};
|
||||
use freetype::freetype::{FT_STYLE_FLAG_ITALIC, FT_STYLE_FLAG_BOLD};
|
||||
use freetype::freetype::{FT_SizeRec, FT_UInt, FT_Size_Metrics};
|
||||
use freetype::freetype::{ft_sfnt_os2};
|
||||
use freetype::tt_os2::TT_OS2;
|
||||
|
||||
use std::cast;
|
||||
use std::ptr;
|
||||
use std::str;
|
||||
|
||||
fn float_to_fixed_ft(f: float) -> i32 {
|
||||
float_to_fixed(6, f)
|
||||
}
|
||||
|
||||
fn fixed_to_float_ft(f: i32) -> float {
|
||||
fixed_to_float(6, f)
|
||||
}
|
||||
|
||||
pub struct FontTable {
|
||||
bogus: ()
|
||||
}
|
||||
|
||||
impl FontTableMethods for FontTable {
|
||||
fn with_buffer(&self, _blk: &fn(*u8, uint)) {
|
||||
fail!()
|
||||
}
|
||||
}
|
||||
|
||||
enum FontSource {
|
||||
FontSourceMem(~[u8]),
|
||||
FontSourceFile(~str)
|
||||
}
|
||||
|
||||
pub struct FontHandle {
|
||||
// The font binary. This must stay valid for the lifetime of the font,
|
||||
// if the font is created using FT_Memory_Face.
|
||||
source: FontSource,
|
||||
face: FT_Face,
|
||||
handle: FontContextHandle
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for FontHandle {
|
||||
fn drop(&self) {
|
||||
assert!(self.face.is_not_null());
|
||||
unsafe {
|
||||
if !FT_Done_Face(self.face).succeeded() {
|
||||
fail!(~"FT_Done_Face failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FontHandleMethods for FontHandle {
|
||||
fn new_from_buffer(fctx: &FontContextHandle,
|
||||
buf: ~[u8],
|
||||
style: &SpecifiedFontStyle)
|
||||
-> Result<FontHandle, ()> {
|
||||
let ft_ctx: FT_Library = fctx.ctx.ctx;
|
||||
if ft_ctx.is_null() { return Err(()); }
|
||||
|
||||
let face_result = do buf.as_imm_buf |bytes: *u8, len: uint| {
|
||||
create_face_from_buffer(ft_ctx, bytes, len, style.pt_size)
|
||||
};
|
||||
|
||||
// TODO: this could be more simply written as result::chain
|
||||
// and moving buf into the struct ctor, but cant' move out of
|
||||
// captured binding.
|
||||
return match face_result {
|
||||
Ok(face) => {
|
||||
let handle = FontHandle {
|
||||
face: face,
|
||||
source: FontSourceMem(buf),
|
||||
handle: *fctx
|
||||
};
|
||||
Ok(handle)
|
||||
}
|
||||
Err(()) => Err(())
|
||||
};
|
||||
|
||||
fn create_face_from_buffer(lib: FT_Library,
|
||||
cbuf: *u8, cbuflen: uint, pt_size: float)
|
||||
-> Result<FT_Face, ()> {
|
||||
|
||||
unsafe {
|
||||
let mut face: FT_Face = ptr::null();
|
||||
let face_index = 0 as FT_Long;
|
||||
let result = FT_New_Memory_Face(lib, cbuf, cbuflen as FT_Long,
|
||||
face_index, ptr::to_mut_unsafe_ptr(&mut face));
|
||||
|
||||
if !result.succeeded() || face.is_null() {
|
||||
return Err(());
|
||||
}
|
||||
if FontHandle::set_char_size(face, pt_size).is_ok() {
|
||||
Ok(face)
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// an identifier usable by FontContextHandle to recreate this FontHandle.
|
||||
fn face_identifier(&self) -> ~str {
|
||||
/* FT_Get_Postscript_Name seems like a better choice here, but it
|
||||
doesn't give usable results for fontconfig when deserializing. */
|
||||
unsafe { str::raw::from_c_str((*self.face).family_name) }
|
||||
}
|
||||
fn family_name(&self) -> ~str {
|
||||
unsafe { str::raw::from_c_str((*self.face).family_name) }
|
||||
}
|
||||
fn face_name(&self) -> ~str {
|
||||
unsafe { str::raw::from_c_str(FT_Get_Postscript_Name(self.face)) }
|
||||
}
|
||||
fn is_italic(&self) -> bool {
|
||||
unsafe { (*self.face).style_flags & FT_STYLE_FLAG_ITALIC != 0 }
|
||||
}
|
||||
fn boldness(&self) -> CSSFontWeight {
|
||||
let default_weight = FontWeight400;
|
||||
if unsafe { (*self.face).style_flags & FT_STYLE_FLAG_BOLD == 0 } {
|
||||
default_weight
|
||||
} else {
|
||||
unsafe {
|
||||
let os2 = FT_Get_Sfnt_Table(self.face, ft_sfnt_os2) as *TT_OS2;
|
||||
let valid = os2.is_not_null() && (*os2).version != 0xffff;
|
||||
if valid {
|
||||
let weight =(*os2).usWeightClass;
|
||||
match weight {
|
||||
1 | 100..199 => FontWeight100,
|
||||
2 | 200..299 => FontWeight200,
|
||||
3 | 300..399 => FontWeight300,
|
||||
4 | 400..499 => FontWeight400,
|
||||
5 | 500..599 => FontWeight500,
|
||||
6 | 600..699 => FontWeight600,
|
||||
7 | 700..799 => FontWeight700,
|
||||
8 | 800..899 => FontWeight800,
|
||||
9 | 900..999 => FontWeight900,
|
||||
_ => default_weight
|
||||
}
|
||||
} else {
|
||||
default_weight
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn clone_with_style(&self,
|
||||
fctx: &FontContextHandle,
|
||||
style: &UsedFontStyle) -> Result<FontHandle, ()> {
|
||||
match self.source {
|
||||
FontSourceMem(ref buf) => {
|
||||
FontHandleMethods::new_from_buffer(fctx, buf.clone(), style)
|
||||
}
|
||||
FontSourceFile(ref file) => {
|
||||
FontHandle::new_from_file(fctx, (*file).clone(), style)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn glyph_index(&self,
|
||||
codepoint: char) -> Option<GlyphIndex> {
|
||||
assert!(self.face.is_not_null());
|
||||
unsafe {
|
||||
let idx = FT_Get_Char_Index(self.face, codepoint as FT_ULong);
|
||||
return if idx != 0 as FT_UInt {
|
||||
Some(idx as GlyphIndex)
|
||||
} else {
|
||||
debug!("Invalid codepoint: %?", codepoint);
|
||||
None
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn glyph_h_advance(&self,
|
||||
glyph: GlyphIndex) -> Option<FractionalPixel> {
|
||||
assert!(self.face.is_not_null());
|
||||
unsafe {
|
||||
let res = FT_Load_Glyph(self.face, glyph as FT_UInt, 0);
|
||||
if res.succeeded() {
|
||||
let void_glyph = (*self.face).glyph;
|
||||
let slot: FT_GlyphSlot = cast::transmute(void_glyph);
|
||||
assert!(slot.is_not_null());
|
||||
debug!("metrics: %?", (*slot).metrics);
|
||||
let advance = (*slot).metrics.horiAdvance;
|
||||
debug!("h_advance for %? is %?", glyph, advance);
|
||||
let advance = advance as i32;
|
||||
return Some(fixed_to_float_ft(advance) as FractionalPixel);
|
||||
} else {
|
||||
debug!("Unable to load glyph %?. reason: %?", glyph, res);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_metrics(&self) -> FontMetrics {
|
||||
/* TODO(Issue #76): complete me */
|
||||
let face = self.get_face_rec();
|
||||
|
||||
let underline_size = self.font_units_to_au(face.underline_thickness as float);
|
||||
let underline_offset = self.font_units_to_au(face.underline_position as float);
|
||||
let em_size = self.font_units_to_au(face.units_per_EM as float);
|
||||
let ascent = self.font_units_to_au(face.ascender as float);
|
||||
let descent = self.font_units_to_au(face.descender as float);
|
||||
let max_advance = self.font_units_to_au(face.max_advance_width as float);
|
||||
|
||||
return FontMetrics {
|
||||
underline_size: underline_size,
|
||||
underline_offset: underline_offset,
|
||||
leading: geometry::from_pt(0.0), //FIXME
|
||||
x_height: geometry::from_pt(0.0), //FIXME
|
||||
em_size: em_size,
|
||||
ascent: ascent,
|
||||
descent: -descent, // linux font's seem to use the opposite sign from mac
|
||||
max_advance: max_advance
|
||||
}
|
||||
}
|
||||
|
||||
fn get_table_for_tag(&self, _: FontTableTag) -> Option<FontTable> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<'self> FontHandle {
|
||||
fn set_char_size(face: FT_Face, pt_size: float) -> Result<(), ()>{
|
||||
let char_width = float_to_fixed_ft(pt_size) as FT_F26Dot6;
|
||||
let char_height = float_to_fixed_ft(pt_size) as FT_F26Dot6;
|
||||
let h_dpi = 72;
|
||||
let v_dpi = 72;
|
||||
|
||||
unsafe {
|
||||
let result = FT_Set_Char_Size(face, char_width, char_height, h_dpi, v_dpi);
|
||||
if result.succeeded() { Ok(()) } else { Err(()) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_from_file(fctx: &FontContextHandle, file: ~str,
|
||||
style: &SpecifiedFontStyle) -> Result<FontHandle, ()> {
|
||||
unsafe {
|
||||
let ft_ctx: FT_Library = fctx.ctx.ctx;
|
||||
if ft_ctx.is_null() { return Err(()); }
|
||||
|
||||
let mut face: FT_Face = ptr::null();
|
||||
let face_index = 0 as FT_Long;
|
||||
do file.to_c_str().with_ref |file_str| {
|
||||
FT_New_Face(ft_ctx, file_str,
|
||||
face_index, ptr::to_mut_unsafe_ptr(&mut face));
|
||||
}
|
||||
if face.is_null() {
|
||||
return Err(());
|
||||
}
|
||||
if FontHandle::set_char_size(face, style.pt_size).is_ok() {
|
||||
Ok(FontHandle {
|
||||
source: FontSourceFile(file),
|
||||
face: face,
|
||||
handle: *fctx
|
||||
})
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_from_file_unstyled(fctx: &FontContextHandle, file: ~str)
|
||||
-> Result<FontHandle, ()> {
|
||||
unsafe {
|
||||
let ft_ctx: FT_Library = fctx.ctx.ctx;
|
||||
if ft_ctx.is_null() { return Err(()); }
|
||||
|
||||
let mut face: FT_Face = ptr::null();
|
||||
let face_index = 0 as FT_Long;
|
||||
do file.to_c_str().with_ref |file_str| {
|
||||
FT_New_Face(ft_ctx, file_str,
|
||||
face_index, ptr::to_mut_unsafe_ptr(&mut face));
|
||||
}
|
||||
if face.is_null() {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
Ok(FontHandle {
|
||||
source: FontSourceFile(file),
|
||||
face: face,
|
||||
handle: *fctx
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn get_face_rec(&'self self) -> &'self FT_FaceRec {
|
||||
unsafe {
|
||||
&(*self.face)
|
||||
}
|
||||
}
|
||||
|
||||
fn font_units_to_au(&self, value: float) -> Au {
|
||||
let face = self.get_face_rec();
|
||||
|
||||
// face.size is a *c_void in the bindings, presumably to avoid
|
||||
// recursive structural types
|
||||
let size: &FT_SizeRec = unsafe { cast::transmute(&(*face.size)) };
|
||||
let metrics: &FT_Size_Metrics = &(*size).metrics;
|
||||
|
||||
let em_size = face.units_per_EM as float;
|
||||
let x_scale = (metrics.x_ppem as float) / em_size as float;
|
||||
|
||||
// If this isn't true then we're scaling one of the axes wrong
|
||||
assert!(metrics.x_ppem == metrics.y_ppem);
|
||||
|
||||
return geometry::from_frac_px(value * x_scale);
|
||||
}
|
||||
}
|
||||
|
60
src/components/gfx/platform/android/font_context.rs
Normal file
60
src/components/gfx/platform/android/font_context.rs
Normal file
|
@ -0,0 +1,60 @@
|
|||
/* 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/. */
|
||||
|
||||
use font::UsedFontStyle;
|
||||
use platform::font::FontHandle;
|
||||
use font_context::FontContextHandleMethods;
|
||||
use platform::font_list::path_from_identifier;
|
||||
|
||||
use freetype::freetype::{FTErrorMethods, FT_Library};
|
||||
use freetype::freetype::{FT_Done_FreeType, FT_Init_FreeType};
|
||||
|
||||
use std::ptr;
|
||||
|
||||
struct FreeTypeLibraryHandle {
|
||||
ctx: FT_Library,
|
||||
}
|
||||
|
||||
impl Drop for FreeTypeLibraryHandle {
|
||||
fn drop(&self) {
|
||||
assert!(self.ctx.is_not_null());
|
||||
unsafe {
|
||||
FT_Done_FreeType(self.ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FontContextHandle {
|
||||
ctx: @FreeTypeLibraryHandle,
|
||||
}
|
||||
|
||||
impl FontContextHandle {
|
||||
pub fn new() -> FontContextHandle {
|
||||
unsafe {
|
||||
let ctx: FT_Library = ptr::null();
|
||||
let result = FT_Init_FreeType(ptr::to_unsafe_ptr(&ctx));
|
||||
if !result.succeeded() { fail!(); }
|
||||
|
||||
FontContextHandle {
|
||||
ctx: @FreeTypeLibraryHandle { ctx: ctx },
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FontContextHandleMethods for FontContextHandle {
|
||||
fn clone(&self) -> FontContextHandle {
|
||||
FontContextHandle { ctx: self.ctx }
|
||||
}
|
||||
|
||||
fn create_font_from_identifier(&self, name: ~str, style: UsedFontStyle)
|
||||
-> Result<FontHandle, ()> {
|
||||
debug!("Creating font handle for %s", name);
|
||||
do path_from_identifier(name, &style).chain |file_name| {
|
||||
debug!("Opening font face %s", file_name);
|
||||
FontHandle::new_from_file(self, file_name, &style)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
205
src/components/gfx/platform/android/font_list.rs
Normal file
205
src/components/gfx/platform/android/font_list.rs
Normal file
|
@ -0,0 +1,205 @@
|
|||
/* 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/. */
|
||||
|
||||
extern mod freetype;
|
||||
extern mod fontconfig;
|
||||
|
||||
use fontconfig::fontconfig::{
|
||||
FcChar8, FcResultMatch, FcSetSystem, FcPattern,
|
||||
FcResultNoMatch, FcMatchPattern, FC_SLANT_ITALIC, FC_WEIGHT_BOLD
|
||||
};
|
||||
use fontconfig::fontconfig::{
|
||||
FcConfigGetCurrent, FcConfigGetFonts, FcPatternGetString,
|
||||
FcPatternDestroy, FcFontSetDestroy, FcConfigSubstitute,
|
||||
FcDefaultSubstitute, FcPatternCreate, FcPatternAddString, FcPatternAddInteger,
|
||||
FcFontMatch, FcFontSetList, FcObjectSetCreate, FcObjectSetDestroy,
|
||||
FcObjectSetAdd, FcPatternGetInteger
|
||||
};
|
||||
|
||||
|
||||
use font::{FontHandleMethods, UsedFontStyle};
|
||||
use font_context::FontContextHandleMethods;
|
||||
use font_list::{FontEntry, FontFamily, FontFamilyMap};
|
||||
use platform::font::FontHandle;
|
||||
use platform::font_context::FontContextHandle;
|
||||
|
||||
use std::hashmap::HashMap;
|
||||
use std::libc;
|
||||
use std::libc::{c_int, c_char};
|
||||
use std::ptr;
|
||||
use std::str;
|
||||
|
||||
pub struct FontListHandle {
|
||||
fctx: FontContextHandle,
|
||||
}
|
||||
|
||||
impl FontListHandle {
|
||||
pub fn new(fctx: &FontContextHandle) -> FontListHandle {
|
||||
FontListHandle { fctx: fctx.clone() }
|
||||
}
|
||||
|
||||
pub fn get_available_families(&self) -> FontFamilyMap {
|
||||
let mut family_map : FontFamilyMap = HashMap::new();
|
||||
unsafe {
|
||||
let config = FcConfigGetCurrent();
|
||||
let fontSet = FcConfigGetFonts(config, FcSetSystem);
|
||||
for i in range(0, (*fontSet).nfont as int) {
|
||||
let font = (*fontSet).fonts.offset(i);
|
||||
let family: *FcChar8 = ptr::null();
|
||||
let mut v: c_int = 0;
|
||||
do "family".to_c_str().with_ref |FC_FAMILY| {
|
||||
while FcPatternGetString(*font, FC_FAMILY, v, &family) == FcResultMatch {
|
||||
let family_name = str::raw::from_c_str(family as *c_char);
|
||||
debug!("Creating new FontFamily for family: %s", family_name);
|
||||
let new_family = @mut FontFamily::new(family_name);
|
||||
family_map.insert(family_name, new_family);
|
||||
v += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return family_map;
|
||||
}
|
||||
|
||||
pub fn load_variations_for_family(&self, family: @mut FontFamily) {
|
||||
debug!("getting variations for %?", family);
|
||||
unsafe {
|
||||
let config = FcConfigGetCurrent();
|
||||
let font_set = FcConfigGetFonts(config, FcSetSystem);
|
||||
let font_set_array_ptr = ptr::to_unsafe_ptr(&font_set);
|
||||
let pattern = FcPatternCreate();
|
||||
assert!(pattern.is_not_null());
|
||||
do "family".to_c_str().with_ref |FC_FAMILY| {
|
||||
do family.family_name.to_c_str().with_ref |family_name| {
|
||||
let ok = FcPatternAddString(pattern, FC_FAMILY, family_name as *FcChar8);
|
||||
assert!(ok != 0);
|
||||
}
|
||||
}
|
||||
|
||||
let object_set = FcObjectSetCreate();
|
||||
assert!(object_set.is_not_null());
|
||||
|
||||
do "file".to_c_str().with_ref |FC_FILE| {
|
||||
FcObjectSetAdd(object_set, FC_FILE);
|
||||
}
|
||||
do "index".to_c_str().with_ref |FC_INDEX| {
|
||||
FcObjectSetAdd(object_set, FC_INDEX);
|
||||
}
|
||||
|
||||
let matches = FcFontSetList(config, font_set_array_ptr, 1, pattern, object_set);
|
||||
|
||||
debug!("found %? variations", (*matches).nfont);
|
||||
|
||||
for i in range(0, (*matches).nfont as int) {
|
||||
let font = (*matches).fonts.offset(i);
|
||||
let file = do "file".to_c_str().with_ref |FC_FILE| {
|
||||
let file: *FcChar8 = ptr::null();
|
||||
if FcPatternGetString(*font, FC_FILE, 0, &file) == FcResultMatch {
|
||||
str::raw::from_c_str(file as *libc::c_char)
|
||||
} else {
|
||||
fail!();
|
||||
}
|
||||
};
|
||||
let index = do "index".to_c_str().with_ref |FC_INDEX| {
|
||||
let index: libc::c_int = 0;
|
||||
if FcPatternGetInteger(*font, FC_INDEX, 0, &index) == FcResultMatch {
|
||||
index
|
||||
} else {
|
||||
fail!();
|
||||
}
|
||||
};
|
||||
|
||||
debug!("variation file: %?", file);
|
||||
debug!("variation index: %?", index);
|
||||
|
||||
let font_handle = FontHandle::new_from_file_unstyled(&self.fctx,
|
||||
file);
|
||||
let font_handle = font_handle.unwrap();
|
||||
|
||||
debug!("Creating new FontEntry for face: %s", font_handle.face_name());
|
||||
let entry = @FontEntry::new(font_handle);
|
||||
family.entries.push(entry);
|
||||
}
|
||||
|
||||
FcFontSetDestroy(matches);
|
||||
FcPatternDestroy(pattern);
|
||||
FcObjectSetDestroy(object_set);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_last_resort_font_families() -> ~[~str] {
|
||||
~[~"Roboto"]
|
||||
}
|
||||
}
|
||||
|
||||
struct AutoPattern {
|
||||
pattern: *FcPattern
|
||||
}
|
||||
|
||||
impl Drop for AutoPattern {
|
||||
fn drop(&self) {
|
||||
unsafe {
|
||||
FcPatternDestroy(self.pattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn path_from_identifier(name: ~str, style: &UsedFontStyle) -> Result<~str, ()> {
|
||||
unsafe {
|
||||
let config = FcConfigGetCurrent();
|
||||
let wrapper = AutoPattern { pattern: FcPatternCreate() };
|
||||
let pattern = wrapper.pattern;
|
||||
let res = do "family".to_c_str().with_ref |FC_FAMILY| {
|
||||
do name.to_c_str().with_ref |family| {
|
||||
FcPatternAddString(pattern, FC_FAMILY, family as *FcChar8)
|
||||
}
|
||||
};
|
||||
if res != 1 {
|
||||
debug!("adding family to pattern failed");
|
||||
return Err(());
|
||||
}
|
||||
|
||||
if style.italic {
|
||||
let res = do "slant".to_c_str().with_ref |FC_SLANT| {
|
||||
FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC)
|
||||
};
|
||||
if res != 1 {
|
||||
debug!("adding slant to pattern failed");
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
if style.weight.is_bold() {
|
||||
let res = do "weight".to_c_str().with_ref |FC_WEIGHT| {
|
||||
FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD)
|
||||
};
|
||||
if res != 1 {
|
||||
debug!("adding weight to pattern failed");
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
|
||||
if FcConfigSubstitute(config, pattern, FcMatchPattern) != 1 {
|
||||
debug!("substitution failed");
|
||||
return Err(());
|
||||
}
|
||||
FcDefaultSubstitute(pattern);
|
||||
let result = FcResultNoMatch;
|
||||
let result_wrapper = AutoPattern { pattern: FcFontMatch(config, pattern, &result) };
|
||||
let result_pattern = result_wrapper.pattern;
|
||||
if result != FcResultMatch && result_pattern.is_null() {
|
||||
debug!("obtaining match to pattern failed");
|
||||
return Err(());
|
||||
}
|
||||
|
||||
let file: *FcChar8 = ptr::null();
|
||||
let res = do "file".to_c_str().with_ref |FC_FILE| {
|
||||
FcPatternGetString(result_pattern, FC_FILE, 0, &file)
|
||||
};
|
||||
if res != FcResultMatch {
|
||||
debug!("getting filename for font failed");
|
||||
return Err(());
|
||||
}
|
||||
Ok(str::raw::from_c_str(file as *c_char))
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#[cfg(target_os="linux")] pub use platform::linux::{font, font_context, font_list};
|
||||
#[cfg(target_os="macos")] pub use platform::macos::{font, font_context, font_list};
|
||||
#[cfg(target_os="android")] pub use platform::android::{font, font_context, font_list};
|
||||
|
||||
#[cfg(target_os="linux")]
|
||||
pub mod linux {
|
||||
|
@ -19,3 +20,9 @@ pub mod macos {
|
|||
pub mod font_list;
|
||||
}
|
||||
|
||||
#[cfg(target_os="android")]
|
||||
pub mod android {
|
||||
pub mod font;
|
||||
pub mod font_context;
|
||||
pub mod font_list;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@ use std::util::replace;
|
|||
use gfx::render_task::BufferRequest;
|
||||
use servo_msg::compositor_msg::Tile;
|
||||
|
||||
static HEADER: &'static str = "<!DOCTYPE html><html>";
|
||||
|
||||
/// Parent to all quadtree nodes. Stores variables needed at all levels. All method calls
|
||||
/// at this level are in pixel coordinates.
|
||||
pub struct Quadtree<T> {
|
||||
|
@ -298,7 +300,6 @@ impl<T: Tile> Quadtree<T> {
|
|||
|
||||
/// Generate html to visualize the tree. For debugging purposes only.
|
||||
pub fn get_html(&self) -> ~str {
|
||||
static HEADER: &'static str = "<!DOCTYPE html><html>";
|
||||
fmt!("%s<body>%s</body></html>", HEADER, self.root.get_html())
|
||||
}
|
||||
|
||||
|
|
247
src/components/main/platform/common/glut_windowing.rs
Normal file
247
src/components/main/platform/common/glut_windowing.rs
Normal file
|
@ -0,0 +1,247 @@
|
|||
/* 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/. */
|
||||
|
||||
//! A windowing implementation using GLUT.
|
||||
|
||||
use windowing::{ApplicationMethods, WindowEvent, WindowMethods};
|
||||
use windowing::{IdleWindowEvent, ResizeWindowEvent, LoadUrlWindowEvent, MouseWindowEventClass};
|
||||
use windowing::{ScrollWindowEvent, ZoomWindowEvent, NavigationWindowEvent, FinishedWindowEvent};
|
||||
use windowing::{QuitWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEvent, MouseWindowMouseUpEvent};
|
||||
use windowing::{Forward, Back};
|
||||
|
||||
use alert::{Alert, AlertMethods};
|
||||
use std::libc::c_int;
|
||||
use geom::point::Point2D;
|
||||
use geom::size::Size2D;
|
||||
use servo_msg::compositor_msg::{IdleRenderState, RenderState, RenderingRenderState};
|
||||
use servo_msg::compositor_msg::{FinishedLoading, Blank, Loading, PerformingLayout, ReadyState};
|
||||
|
||||
use glut::glut::{ACTIVE_CTRL, ACTIVE_SHIFT, DOUBLE, HAVE_PRECISE_MOUSE_WHEEL, WindowHeight};
|
||||
use glut::glut::WindowWidth;
|
||||
use glut::glut;
|
||||
|
||||
static THROBBER: [char, ..8] = [ '⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷' ];
|
||||
|
||||
/// A structure responsible for setting up and tearing down the entire windowing system.
|
||||
pub struct Application;
|
||||
|
||||
impl ApplicationMethods for Application {
|
||||
fn new() -> Application {
|
||||
glut::init();
|
||||
glut::init_display_mode(DOUBLE);
|
||||
Application
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Application {
|
||||
fn drop(&self) {
|
||||
}
|
||||
}
|
||||
|
||||
/// The type of a window.
|
||||
pub struct Window {
|
||||
glut_window: glut::Window,
|
||||
|
||||
event_queue: @mut ~[WindowEvent],
|
||||
|
||||
drag_origin: Point2D<c_int>,
|
||||
|
||||
mouse_down_button: @mut c_int,
|
||||
mouse_down_point: @mut Point2D<c_int>,
|
||||
|
||||
ready_state: ReadyState,
|
||||
render_state: RenderState,
|
||||
throbber_frame: u8,
|
||||
}
|
||||
|
||||
impl WindowMethods<Application> for Window {
|
||||
/// Creates a new window.
|
||||
fn new(_: &Application) -> @mut Window {
|
||||
// Create the GLUT window.
|
||||
unsafe { glut::glutInitWindowSize(800, 600); }
|
||||
let glut_window = glut::create_window(~"Servo");
|
||||
|
||||
// Create our window object.
|
||||
let window = @mut Window {
|
||||
glut_window: glut_window,
|
||||
|
||||
event_queue: @mut ~[],
|
||||
|
||||
drag_origin: Point2D(0 as c_int, 0),
|
||||
|
||||
mouse_down_button: @mut 0,
|
||||
mouse_down_point: @mut Point2D(0 as c_int, 0),
|
||||
|
||||
ready_state: Blank,
|
||||
render_state: IdleRenderState,
|
||||
throbber_frame: 0,
|
||||
};
|
||||
|
||||
let event_queue = window.event_queue;
|
||||
|
||||
// Register event handlers.
|
||||
do glut::reshape_func(window.glut_window) |width, height| {
|
||||
event_queue.push(ResizeWindowEvent(width as uint, height as uint))
|
||||
}
|
||||
do glut::keyboard_func |key, _, _| {
|
||||
window.handle_key(key)
|
||||
}
|
||||
do glut::mouse_func |button, state, x, y| {
|
||||
if button < 3 {
|
||||
window.handle_mouse(button, state, x, y);
|
||||
}
|
||||
else {
|
||||
match button {
|
||||
3 => {
|
||||
event_queue.push(ScrollWindowEvent(Point2D(0.0, 5.0 as f32), Point2D(0.0 as i32, 5.0 as i32)));
|
||||
},
|
||||
4 => {
|
||||
event_queue.push(ScrollWindowEvent(Point2D(0.0, -5.0 as f32), Point2D(0.0 as i32, -5.0 as i32)));
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window
|
||||
}
|
||||
|
||||
/// Returns the size of the window.
|
||||
fn size(&self) -> Size2D<f32> {
|
||||
Size2D(glut::get(WindowWidth) as f32, glut::get(WindowHeight) as f32)
|
||||
}
|
||||
|
||||
/// Presents the window to the screen (perhaps by page flipping).
|
||||
fn present(&mut self) {
|
||||
glut::swap_buffers();
|
||||
}
|
||||
|
||||
fn recv(@mut self) -> WindowEvent {
|
||||
if !self.event_queue.is_empty() {
|
||||
return self.event_queue.shift()
|
||||
}
|
||||
glut::check_loop();
|
||||
if !self.event_queue.is_empty() {
|
||||
self.event_queue.shift()
|
||||
} else {
|
||||
IdleWindowEvent
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the ready state.
|
||||
fn set_ready_state(@mut self, ready_state: ReadyState) {
|
||||
self.ready_state = ready_state;
|
||||
//FIXME: set_window_title causes crash with Android version of freeGLUT. Temporarily blocked.
|
||||
//self.update_window_title()
|
||||
}
|
||||
|
||||
/// Sets the render state.
|
||||
fn set_render_state(@mut self, render_state: RenderState) {
|
||||
if self.ready_state == FinishedLoading &&
|
||||
self.render_state == RenderingRenderState &&
|
||||
render_state == IdleRenderState {
|
||||
// page loaded
|
||||
self.event_queue.push(FinishedWindowEvent);
|
||||
}
|
||||
|
||||
self.render_state = render_state;
|
||||
//FIXME: set_window_title causes crash with Android version of freeGLUT. Temporarily blocked.
|
||||
//self.update_window_title()
|
||||
}
|
||||
|
||||
fn hidpi_factor(@mut self) -> f32 {
|
||||
//FIXME: Do nothing in GLUT now.
|
||||
0f32
|
||||
}
|
||||
}
|
||||
|
||||
impl Window {
|
||||
/// Helper function to set the window title in accordance with the ready state.
|
||||
fn update_window_title(&self) {
|
||||
let throbber = THROBBER[self.throbber_frame];
|
||||
match self.ready_state {
|
||||
Blank => {
|
||||
glut::set_window_title(self.glut_window, fmt!("Blank"))
|
||||
}
|
||||
Loading => {
|
||||
glut::set_window_title(self.glut_window, fmt!("%c Loading . Servo", throbber))
|
||||
}
|
||||
PerformingLayout => {
|
||||
glut::set_window_title(self.glut_window, fmt!("%c Performing Layout . Servo", throbber))
|
||||
}
|
||||
FinishedLoading => {
|
||||
match self.render_state {
|
||||
RenderingRenderState => {
|
||||
glut::set_window_title(self.glut_window, fmt!("%c Rendering . Servo", throbber))
|
||||
}
|
||||
IdleRenderState => glut::set_window_title(self.glut_window, "Servo"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function to handle keyboard events.
|
||||
fn handle_key(&self, key: u8) {
|
||||
debug!("got key: %?", key);
|
||||
let modifiers = glut::get_modifiers();
|
||||
match key {
|
||||
42 => self.load_url(),
|
||||
43 => self.event_queue.push(ZoomWindowEvent(1.1)),
|
||||
45 => self.event_queue.push(ZoomWindowEvent(0.909090909)),
|
||||
56 => self.event_queue.push(ScrollWindowEvent(Point2D(0.0, 5.0 as f32), Point2D(0.0 as i32, 5.0 as i32))),
|
||||
50 => self.event_queue.push(ScrollWindowEvent(Point2D(0.0, -5.0 as f32), Point2D(0.0 as i32, -5.0 as i32))),
|
||||
127 => {
|
||||
if (modifiers & ACTIVE_SHIFT) != 0 {
|
||||
self.event_queue.push(NavigationWindowEvent(Forward));
|
||||
}
|
||||
else {
|
||||
self.event_queue.push(NavigationWindowEvent(Back));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function to handle a click
|
||||
fn handle_mouse(&self, button: c_int, state: c_int, x: c_int, y: c_int) {
|
||||
// FIXME(tkuehn): max pixel dist should be based on pixel density
|
||||
let max_pixel_dist = 10f;
|
||||
let event = match state {
|
||||
glut::MOUSE_DOWN => {
|
||||
*self.mouse_down_point = Point2D(x, y);
|
||||
*self.mouse_down_button = button;
|
||||
MouseWindowMouseDownEvent(button as uint, Point2D(x as f32, y as f32))
|
||||
}
|
||||
glut::MOUSE_UP => {
|
||||
if *self.mouse_down_button == button {
|
||||
let pixel_dist = *self.mouse_down_point - Point2D(x, y);
|
||||
let pixel_dist = ((pixel_dist.x * pixel_dist.x +
|
||||
pixel_dist.y * pixel_dist.y) as float).sqrt();
|
||||
if pixel_dist < max_pixel_dist {
|
||||
let click_event = MouseWindowClickEvent(button as uint,
|
||||
Point2D(x as f32, y as f32));
|
||||
self.event_queue.push(MouseWindowEventClass(click_event));
|
||||
}
|
||||
}
|
||||
MouseWindowMouseUpEvent(button as uint, Point2D(x as f32, y as f32))
|
||||
}
|
||||
_ => fail!("I cannot recognize the type of mouse action that occured. :-(")
|
||||
};
|
||||
self.event_queue.push(MouseWindowEventClass(event));
|
||||
}
|
||||
|
||||
/// Helper function to pop up an alert box prompting the user to load a URL.
|
||||
fn load_url(&self) {
|
||||
let mut alert: Alert = AlertMethods::new("Navigate to:");
|
||||
alert.add_prompt();
|
||||
alert.run();
|
||||
let value = alert.prompt_value();
|
||||
if "" == value { // To avoid crashing on Linux.
|
||||
self.event_queue.push(LoadUrlWindowEvent(~"http://purple.com/"))
|
||||
} else {
|
||||
self.event_queue.push(LoadUrlWindowEvent(value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,13 +4,17 @@
|
|||
|
||||
//! Platform-specific functionality for Servo.
|
||||
|
||||
#[cfg(not(shared_gl_windowing))]
|
||||
#[cfg(not(shared_gl_windowing), target_os="android")]
|
||||
pub use platform::common::glut_windowing::{Application, Window};
|
||||
#[cfg(not(shared_gl_windowing), not(target_os="android"))]
|
||||
pub use platform::common::glfw_windowing::{Application, Window};
|
||||
#[cfg(shared_gl_windowing)]
|
||||
pub use platform::common::shared_gl_windowing::{Application, Window};
|
||||
|
||||
pub mod common {
|
||||
#[cfg(not(shared_gl_windowing))]
|
||||
#[cfg(not(shared_gl_windowing), target_os="android")]
|
||||
pub mod glut_windowing;
|
||||
#[cfg(not(shared_gl_windowing), not(target_os="android"))]
|
||||
pub mod glfw_windowing;
|
||||
#[cfg(shared_gl_windowing)]
|
||||
pub mod shared_gl_windowing;
|
||||
|
|
|
@ -15,8 +15,11 @@ extern mod alert;
|
|||
extern mod azure;
|
||||
extern mod geom;
|
||||
extern mod gfx (name = "gfx");
|
||||
#[cfg(not(target_os="android"))]
|
||||
extern mod glfw;
|
||||
//extern mod http_client;
|
||||
#[cfg(target_os="android")]
|
||||
extern mod glut;
|
||||
extern mod js;
|
||||
extern mod layers;
|
||||
extern mod newcss (name = "css");
|
||||
|
@ -101,9 +104,24 @@ pub mod util;
|
|||
#[cfg(not(test))]
|
||||
#[start]
|
||||
fn start(argc: int, argv: **u8, crate_map: *u8) -> int {
|
||||
#[cfg(target_os="linux")]
|
||||
#[cfg(target_os="macos")]
|
||||
fn getopts() -> Opts {
|
||||
opts::from_cmdline_args(os::args())
|
||||
}
|
||||
#[cfg(target_os="android")]
|
||||
fn getopts() -> Opts {
|
||||
let mut args:~[~str] = ~[];
|
||||
args.push(~"servo");
|
||||
let servo_url = os::getenv(~"SERVO_URL");
|
||||
match servo_url {
|
||||
Some(s) => { args.push(s); },
|
||||
None => { fail!("No url input"); }
|
||||
}
|
||||
opts::from_cmdline_args(args)
|
||||
}
|
||||
do std::rt::start_on_main_thread(argc, argv, crate_map) {
|
||||
let opts = opts::from_cmdline_args(os::args());
|
||||
run(opts)
|
||||
run(getopts())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1563,7 +1563,7 @@ for (uint32_t i = 0; i < length; ++i) {
|
|||
raise TypeError("We don't support nullable enumerated return types "
|
||||
"yet")
|
||||
return ("""assert!((%(result)s as uint) < %(strings)s.len());
|
||||
let %(resultStr)s: *JSString = JS_NewStringCopyN(cx, ptr::to_unsafe_ptr(&%(strings)s[%(result)s as u32].value[0]) as *i8, %(strings)s[%(result)s as u32].length as u64);
|
||||
let %(resultStr)s: *JSString = JS_NewStringCopyN(cx, ptr::to_unsafe_ptr(&%(strings)s[%(result)s as u32].value[0]) as *i8, %(strings)s[%(result)s as u32].length as libc::size_t);
|
||||
if %(resultStr)s.is_null() {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ pub fn _obj_toString(cx: *JSContext, className: *libc::c_char) -> *JSString {
|
|||
unsafe {
|
||||
let name = str::raw::from_c_str(className);
|
||||
let nchars = "[object ]".len() + name.len();
|
||||
let chars: *mut jschar = cast::transmute(JS_malloc(cx, (nchars + 1) as u64 * (size_of::<jschar>() as u64)));
|
||||
let chars: *mut jschar = cast::transmute(JS_malloc(cx, (nchars + 1) as libc::size_t * (size_of::<jschar>() as libc::size_t)));
|
||||
if chars.is_null() {
|
||||
return ptr::null();
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ pub fn _obj_toString(cx: *JSContext, className: *libc::c_char) -> *JSString {
|
|||
*chars.offset(i as int) = c as jschar;
|
||||
}
|
||||
*chars.offset(nchars as int) = 0;
|
||||
let jsstr = JS_NewUCString(cx, cast::transmute(chars), nchars as u64);
|
||||
let jsstr = JS_NewUCString(cx, cast::transmute(chars), nchars as libc::size_t);
|
||||
if jsstr.is_null() {
|
||||
JS_free(cx, cast::transmute(chars));
|
||||
}
|
||||
|
|
|
@ -37,8 +37,8 @@ use js::{JSPROP_SETTER, JSVAL_VOID, JSVAL_TRUE, JSVAL_FALSE};
|
|||
use js::{JS_THIS_OBJECT, JSFUN_CONSTRUCTOR, JS_CALLEE, JSPROP_READONLY};
|
||||
use js;
|
||||
|
||||
static TOSTRING_CLASS_RESERVED_SLOT: u64 = 0;
|
||||
static TOSTRING_NAME_RESERVED_SLOT: u64 = 1;
|
||||
static TOSTRING_CLASS_RESERVED_SLOT: libc::size_t = 0;
|
||||
static TOSTRING_NAME_RESERVED_SLOT: libc::size_t = 1;
|
||||
|
||||
struct GlobalStaticData {
|
||||
proxy_handlers: HashMap<uint, *libc::c_void>,
|
||||
|
|
1
src/platform/android/fontconfig
Submodule
1
src/platform/android/fontconfig
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit d0c6dd720f90e2e8f8d8a103754195096531b531
|
1
src/platform/android/libexpat
Submodule
1
src/platform/android/libexpat
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit e74cfc256285a94b84c5b019714e922d37d0a286
|
1
src/platform/android/libfreetype2
Submodule
1
src/platform/android/libfreetype2
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 3030c434349f39dd16d330b07f3ec6db917ea882
|
|
@ -1 +1 @@
|
|||
Subproject commit c3a603bb641539bb2b7f3c159fd8ea3de045db8f
|
||||
Subproject commit 3f4841a48534b167284ea04b0c2b5952fef936e7
|
1
src/support/glut/rust-glut
Submodule
1
src/support/glut/rust-glut
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 24939d67ce465e3a44bb4adac56534c833478daf
|
|
@ -1 +1 @@
|
|||
Subproject commit dfcdbc7562edb58672438f59ccfa8687cdd47e31
|
||||
Subproject commit c0f176ddc0157b768d689bd1e78f56006b4db488
|
|
@ -1 +1 @@
|
|||
Subproject commit 10a11900d78783655d500121d0afb2810785c022
|
||||
Subproject commit c2feb563c8434319f60b2e9134e250d7bc1fe27f
|
|
@ -1 +1 @@
|
|||
Subproject commit da248d3f5b3ed6d9e804c543563be8e34baf1673
|
||||
Subproject commit 720128629f3395e8836e64887d2c105d94603746
|
|
@ -1 +1 @@
|
|||
Subproject commit 0824ca2895668b6ac1751871d7360bc484afb930
|
||||
Subproject commit 4a9d0c799d12b10cd313b07a7ed6380698429e01
|
|
@ -1 +1 @@
|
|||
Subproject commit bd06cd169cf68de03438f6ab9ab87bc62243774e
|
||||
Subproject commit e677e2586128acfbae7517a4916e7ea826ab3206
|
|
@ -1 +1 @@
|
|||
Subproject commit f889ab32a6fc249b2a8667a7c7c1e5c24d5daf7c
|
||||
Subproject commit db2cd9398c25f4d061d536e3cb53a0a3005ccb87
|
Loading…
Add table
Add a link
Reference in a new issue