Use PEP 8 naming conventions for fontbuilder2
This commit is contained in:
parent
4a049c5f3a
commit
19e7d14506
@ -32,8 +32,8 @@ in particular, let us know and we can try to clarify it.
|
|||||||
|
|
||||||
fontbuilder2
|
fontbuilder2
|
||||||
MIT
|
MIT
|
||||||
unspecified (FontLoader.py)
|
unspecified (font_loader.py)
|
||||||
IBM CPL (Packer.py)
|
IBM CPL (packer.py)
|
||||||
|
|
||||||
i18n
|
i18n
|
||||||
GPL version 2 (or later)
|
GPL version 2 (or later)
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
# list of decimal codepoints (from U+0001 to U+FFFF) for which that font
|
# list of decimal codepoints (from U+0001 to U+FFFF) for which that font
|
||||||
# contains some glyph data.
|
# contains some glyph data.
|
||||||
|
|
||||||
import FontLoader
|
import font_loader
|
||||||
|
|
||||||
|
|
||||||
def dump_font(ttf):
|
def dump_font(ttf):
|
||||||
(face, indexes) = FontLoader.create_cairo_font_face_for_file(
|
(face, indexes) = font_loader.create_cairo_font_face_for_file(
|
||||||
f"../../../binaries/data/tools/fontbuilder/fonts/{ttf}", 0, FontLoader.FT_LOAD_DEFAULT
|
f"../../../binaries/data/tools/fontbuilder/fonts/{ttf}", 0, font_loader.FT_LOAD_DEFAULT
|
||||||
)
|
)
|
||||||
|
|
||||||
mappings = [(c, indexes(chr(c))) for c in range(1, 65535)]
|
mappings = [(c, indexes(chr(c))) for c in range(1, 65535)]
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
import math
|
import math
|
||||||
|
|
||||||
import cairo
|
import cairo
|
||||||
import FontLoader
|
import font_loader
|
||||||
import Packer
|
import packer
|
||||||
|
|
||||||
|
|
||||||
# Representation of a rendered glyph
|
# Representation of a rendered glyph
|
||||||
@ -50,8 +50,8 @@ class Glyph:
|
|||||||
self.w = bb[2] - bb[0]
|
self.w = bb[2] - bb[0]
|
||||||
self.h = bb[3] - bb[1]
|
self.h = bb[3] - bb[1]
|
||||||
|
|
||||||
def pack(self, packer):
|
def pack(self, packer_instance):
|
||||||
self.pos = packer.Pack(self.w, self.h)
|
self.pos = packer_instance.pack(self.w, self.h)
|
||||||
|
|
||||||
def render(self, ctx):
|
def render(self, ctx):
|
||||||
if ctx.get_font_face() != self.face:
|
if ctx.get_font_face() != self.face:
|
||||||
@ -95,41 +95,41 @@ def setup_context(width, height, renderstyle):
|
|||||||
return ctx, surface
|
return ctx, surface
|
||||||
|
|
||||||
|
|
||||||
def generate_font(outname, ttfNames, loadopts, size, renderstyle, dsizes):
|
def generate_font(outname, ttf_names, loadopts, size, renderstyle, dsizes):
|
||||||
faceList = []
|
face_list = []
|
||||||
indexList = []
|
index_list = []
|
||||||
for i in range(len(ttfNames)):
|
for i in range(len(ttf_names)):
|
||||||
(face, indices) = FontLoader.create_cairo_font_face_for_file(
|
(face, indices) = font_loader.create_cairo_font_face_for_file(
|
||||||
f"../../../binaries/data/tools/fontbuilder/fonts/{ttfNames[i]}", 0, loadopts
|
f"../../../binaries/data/tools/fontbuilder/fonts/{ttf_names[i]}", 0, loadopts
|
||||||
)
|
)
|
||||||
faceList.append(face)
|
face_list.append(face)
|
||||||
if ttfNames[i] not in dsizes:
|
if ttf_names[i] not in dsizes:
|
||||||
dsizes[ttfNames[i]] = 0
|
dsizes[ttf_names[i]] = 0
|
||||||
indexList.append(indices)
|
index_list.append(indices)
|
||||||
|
|
||||||
(ctx, _) = setup_context(1, 1, renderstyle)
|
(ctx, _) = setup_context(1, 1, renderstyle)
|
||||||
|
|
||||||
# TODO: this gets the line height from the default font
|
# TODO: this gets the line height from the default font
|
||||||
# while entire texts can be in the fallback font
|
# while entire texts can be in the fallback font
|
||||||
ctx.set_font_face(faceList[0])
|
ctx.set_font_face(face_list[0])
|
||||||
ctx.set_font_size(size + dsizes[ttfNames[0]])
|
ctx.set_font_size(size + dsizes[ttf_names[0]])
|
||||||
(_, _, linespacing, _, _) = ctx.font_extents()
|
(_, _, linespacing, _, _) = ctx.font_extents()
|
||||||
|
|
||||||
# Estimate the 'average' height of text, for vertical center alignment
|
# Estimate the 'average' height of text, for vertical center alignment
|
||||||
charheight = round(ctx.glyph_extents([(indexList[0]("I"), 0.0, 0.0)])[3])
|
charheight = round(ctx.glyph_extents([(index_list[0]("I"), 0.0, 0.0)])[3])
|
||||||
|
|
||||||
# Translate all the characters into glyphs
|
# Translate all the characters into glyphs
|
||||||
# (This is inefficient if multiple characters have the same glyph)
|
# (This is inefficient if multiple characters have the same glyph)
|
||||||
glyphs = []
|
glyphs = []
|
||||||
# for c in chars:
|
# for c in chars:
|
||||||
for c in range(0x20, 0xFFFE):
|
for c in range(0x20, 0xFFFE):
|
||||||
for i in range(len(indexList)):
|
for i in range(len(index_list)):
|
||||||
idx = indexList[i](chr(c))
|
idx = index_list[i](chr(c))
|
||||||
if c == 0xFFFD and idx == 0: # use "?" if the missing-glyph glyph is missing
|
if c == 0xFFFD and idx == 0: # use "?" if the missing-glyph glyph is missing
|
||||||
idx = indexList[i]("?")
|
idx = index_list[i]("?")
|
||||||
if idx:
|
if idx:
|
||||||
glyphs.append(
|
glyphs.append(
|
||||||
Glyph(ctx, renderstyle, chr(c), idx, faceList[i], size + dsizes[ttfNames[i]])
|
Glyph(ctx, renderstyle, chr(c), idx, face_list[i], size + dsizes[ttf_names[i]])
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -149,10 +149,10 @@ def generate_font(outname, ttfNames, loadopts, size, renderstyle, dsizes):
|
|||||||
try:
|
try:
|
||||||
# Using the dump pacher usually creates bigger textures, but runs faster
|
# Using the dump pacher usually creates bigger textures, but runs faster
|
||||||
# In practice the size difference is so small it always ends up in the same size
|
# In practice the size difference is so small it always ends up in the same size
|
||||||
packer = Packer.DumbRectanglePacker(w, h)
|
packer_instance = packer.DumbRectanglePacker(w, h)
|
||||||
for g in glyphs:
|
for g in glyphs:
|
||||||
g.pack(packer)
|
g.pack(packer_instance)
|
||||||
except Packer.OutOfSpaceError:
|
except packer.OutOfSpaceError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
ctx, surface = setup_context(w, h, renderstyle)
|
ctx, surface = setup_context(w, h, renderstyle)
|
||||||
@ -199,12 +199,12 @@ stroked2 = {"colour": True, "stroke": [((0, 0, 0, 1), 2.0)], "fill": [(1, 1, 1,
|
|||||||
stroked3 = {"colour": True, "stroke": [((0, 0, 0, 1), 2.5)], "fill": [(1, 1, 1, 1), (1, 1, 1, 1)]}
|
stroked3 = {"colour": True, "stroke": [((0, 0, 0, 1), 2.5)], "fill": [(1, 1, 1, 1), (1, 1, 1, 1)]}
|
||||||
|
|
||||||
# For extra glyph support, add your preferred font to the font array
|
# For extra glyph support, add your preferred font to the font array
|
||||||
Sans = (["LinBiolinum_Rah.ttf", "FreeSans.ttf"], FontLoader.FT_LOAD_DEFAULT)
|
Sans = (["LinBiolinum_Rah.ttf", "FreeSans.ttf"], font_loader.FT_LOAD_DEFAULT)
|
||||||
Sans_Bold = (["LinBiolinum_RBah.ttf", "FreeSansBold.ttf"], FontLoader.FT_LOAD_DEFAULT)
|
Sans_Bold = (["LinBiolinum_RBah.ttf", "FreeSansBold.ttf"], font_loader.FT_LOAD_DEFAULT)
|
||||||
Sans_Italic = (["LinBiolinum_RIah.ttf", "FreeSansOblique.ttf"], FontLoader.FT_LOAD_DEFAULT)
|
Sans_Italic = (["LinBiolinum_RIah.ttf", "FreeSansOblique.ttf"], font_loader.FT_LOAD_DEFAULT)
|
||||||
SansMono = (["DejaVuSansMono.ttf", "FreeMono.ttf"], FontLoader.FT_LOAD_DEFAULT)
|
SansMono = (["DejaVuSansMono.ttf", "FreeMono.ttf"], font_loader.FT_LOAD_DEFAULT)
|
||||||
Serif = (["texgyrepagella-regular.otf", "FreeSerif.ttf"], FontLoader.FT_LOAD_NO_HINTING)
|
Serif = (["texgyrepagella-regular.otf", "FreeSerif.ttf"], font_loader.FT_LOAD_NO_HINTING)
|
||||||
Serif_Bold = (["texgyrepagella-bold.otf", "FreeSerifBold.ttf"], FontLoader.FT_LOAD_NO_HINTING)
|
Serif_Bold = (["texgyrepagella-bold.otf", "FreeSerifBold.ttf"], font_loader.FT_LOAD_NO_HINTING)
|
||||||
|
|
||||||
# Define the size differences used to render different fallback fonts
|
# Define the size differences used to render different fallback fonts
|
||||||
# I.e. when adding a fallback font has smaller glyphs than the original, you can bump it
|
# I.e. when adding a fallback font has smaller glyphs than the original, you can bump it
|
||||||
|
@ -44,16 +44,16 @@ class RectanglePacker:
|
|||||||
http://www.csc.liv.ac.uk/~epa/surveyhtml.html
|
http://www.csc.liv.ac.uk/~epa/surveyhtml.html
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, packingAreaWidth, packingAreaHeight):
|
def __init__(self, packing_area_width, packing_area_height):
|
||||||
"""Initialize a new rectangle packer.
|
"""Initialize a new rectangle packer.
|
||||||
|
|
||||||
packingAreaWidth: Maximum width of the packing area
|
packingAreaWidth: Maximum width of the packing area
|
||||||
packingAreaHeight: Maximum height of the packing area
|
packingAreaHeight: Maximum height of the packing area
|
||||||
"""
|
"""
|
||||||
self.packingAreaWidth = packingAreaWidth
|
self.packingAreaWidth = packing_area_width
|
||||||
self.packingAreaHeight = packingAreaHeight
|
self.packingAreaHeight = packing_area_height
|
||||||
|
|
||||||
def Pack(self, rectangleWidth, rectangleHeight):
|
def pack(self, rectangle_width, rectangle_height):
|
||||||
"""Allocate space for a rectangle in the packing area.
|
"""Allocate space for a rectangle in the packing area.
|
||||||
|
|
||||||
rectangleWidth: Width of the rectangle to allocate
|
rectangleWidth: Width of the rectangle to allocate
|
||||||
@ -61,14 +61,14 @@ class RectanglePacker:
|
|||||||
|
|
||||||
Returns the location at which the rectangle has been placed
|
Returns the location at which the rectangle has been placed
|
||||||
"""
|
"""
|
||||||
point = self.TryPack(rectangleWidth, rectangleHeight)
|
point = self.try_pack(rectangle_width, rectangle_height)
|
||||||
|
|
||||||
if not point:
|
if not point:
|
||||||
raise OutOfSpaceError("Rectangle does not fit in packing area")
|
raise OutOfSpaceError("Rectangle does not fit in packing area")
|
||||||
|
|
||||||
return point
|
return point
|
||||||
|
|
||||||
def TryPack(self, rectangleWidth, rectangleHeight):
|
def try_pack(self, rectangle_width, rectangle_height):
|
||||||
"""Try to allocate space for a rectangle in the packing area.
|
"""Try to allocate space for a rectangle in the packing area.
|
||||||
|
|
||||||
rectangleWidth: Width of the rectangle to allocate
|
rectangleWidth: Width of the rectangle to allocate
|
||||||
@ -81,23 +81,23 @@ class RectanglePacker:
|
|||||||
|
|
||||||
|
|
||||||
class DumbRectanglePacker(RectanglePacker):
|
class DumbRectanglePacker(RectanglePacker):
|
||||||
def __init__(self, packingAreaWidth, packingAreaHeight):
|
def __init__(self, packing_area_width, packing_area_height):
|
||||||
RectanglePacker.__init__(self, packingAreaWidth, packingAreaHeight)
|
RectanglePacker.__init__(self, packing_area_width, packing_area_height)
|
||||||
self.x = 0
|
self.x = 0
|
||||||
self.y = 0
|
self.y = 0
|
||||||
self.rowh = 0
|
self.rowh = 0
|
||||||
|
|
||||||
def TryPack(self, rectangleWidth, rectangleHeight):
|
def try_pack(self, rectangle_width, rectangle_height):
|
||||||
if self.x + rectangleWidth >= self.packingAreaWidth:
|
if self.x + rectangle_width >= self.packingAreaWidth:
|
||||||
self.x = 0
|
self.x = 0
|
||||||
self.y += self.rowh
|
self.y += self.rowh
|
||||||
self.rowh = 0
|
self.rowh = 0
|
||||||
if self.y + rectangleHeight >= self.packingAreaHeight:
|
if self.y + rectangle_height >= self.packingAreaHeight:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
r = Point(self.x, self.y)
|
r = Point(self.x, self.y)
|
||||||
self.x += rectangleWidth
|
self.x += rectangle_width
|
||||||
self.rowh = max(self.rowh, rectangleHeight)
|
self.rowh = max(self.rowh, rectangle_height)
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
@ -118,21 +118,21 @@ class CygonRectanglePacker(RectanglePacker):
|
|||||||
analyzed to find the position where the rectangle would achieve the lowest
|
analyzed to find the position where the rectangle would achieve the lowest
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, packingAreaWidth, packingAreaHeight):
|
def __init__(self, packing_area_width, packing_area_height):
|
||||||
"""Initialize a new rectangle packer.
|
"""Initialize a new rectangle packer.
|
||||||
|
|
||||||
packingAreaWidth: Maximum width of the packing area
|
packingAreaWidth: Maximum width of the packing area
|
||||||
packingAreaHeight: Maximum height of the packing area
|
packingAreaHeight: Maximum height of the packing area
|
||||||
"""
|
"""
|
||||||
RectanglePacker.__init__(self, packingAreaWidth, packingAreaHeight)
|
RectanglePacker.__init__(self, packing_area_width, packing_area_height)
|
||||||
|
|
||||||
# Stores the height silhouette of the rectangles
|
# Stores the height silhouette of the rectangles
|
||||||
self.heightSlices = []
|
self.height_slices = []
|
||||||
|
|
||||||
# At the beginning, the packing area is a single slice of height 0
|
# At the beginning, the packing area is a single slice of height 0
|
||||||
self.heightSlices.append(Point(0, 0))
|
self.height_slices.append(Point(0, 0))
|
||||||
|
|
||||||
def TryPack(self, rectangleWidth, rectangleHeight):
|
def try_pack(self, rectangle_width, rectangle_height):
|
||||||
"""Try to allocate space for a rectangle in the packing area.
|
"""Try to allocate space for a rectangle in the packing area.
|
||||||
|
|
||||||
rectangleWidth: Width of the rectangle to allocate
|
rectangleWidth: Width of the rectangle to allocate
|
||||||
@ -145,20 +145,20 @@ class CygonRectanglePacker(RectanglePacker):
|
|||||||
|
|
||||||
# If the rectangle is larger than the packing area in any dimension,
|
# If the rectangle is larger than the packing area in any dimension,
|
||||||
# it will never fit!
|
# it will never fit!
|
||||||
if rectangleWidth > self.packingAreaWidth or rectangleHeight > self.packingAreaHeight:
|
if rectangle_width > self.packingAreaWidth or rectangle_height > self.packingAreaHeight:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Determine the placement for the new rectangle
|
# Determine the placement for the new rectangle
|
||||||
placement = self.tryFindBestPlacement(rectangleWidth, rectangleHeight)
|
placement = self.try_find_best_placement(rectangle_width, rectangle_height)
|
||||||
|
|
||||||
# If a place for the rectangle could be found, update the height slice
|
# If a place for the rectangle could be found, update the height slice
|
||||||
# table to mark the region of the rectangle as being taken.
|
# table to mark the region of the rectangle as being taken.
|
||||||
if placement:
|
if placement:
|
||||||
self.integrateRectangle(placement.x, rectangleWidth, placement.y + rectangleHeight)
|
self.integrate_rectangle(placement.x, rectangle_width, placement.y + rectangle_height)
|
||||||
|
|
||||||
return placement
|
return placement
|
||||||
|
|
||||||
def tryFindBestPlacement(self, rectangleWidth, rectangleHeight):
|
def try_find_best_placement(self, rectangle_width, rectangle_height):
|
||||||
"""Find the best position for a rectangle of the given dimensions.
|
"""Find the best position for a rectangle of the given dimensions.
|
||||||
|
|
||||||
rectangleWidth: Width of the rectangle to find a position for
|
rectangleWidth: Width of the rectangle to find a position for
|
||||||
@ -169,70 +169,70 @@ class CygonRectanglePacker(RectanglePacker):
|
|||||||
"""
|
"""
|
||||||
# Slice index, vertical position and score of the best placement we
|
# Slice index, vertical position and score of the best placement we
|
||||||
# could find
|
# could find
|
||||||
bestSliceIndex = -1 # Slice index where the best placement was found
|
best_slice_index = -1 # Slice index where the best placement was found
|
||||||
bestSliceY = 0 # Y position of the best placement found
|
best_slice_y = 0 # Y position of the best placement found
|
||||||
# lower == better!
|
# lower == better!
|
||||||
bestScore = self.packingAreaHeight
|
best_score = self.packingAreaHeight
|
||||||
|
|
||||||
# This is the counter for the currently checked position. The search
|
# This is the counter for the currently checked position. The search
|
||||||
# works by skipping from slice to slice, determining the suitability
|
# works by skipping from slice to slice, determining the suitability
|
||||||
# of the location for the placement of the rectangle.
|
# of the location for the placement of the rectangle.
|
||||||
leftSliceIndex = 0
|
left_slice_index = 0
|
||||||
|
|
||||||
# Determine the slice in which the right end of the rectangle is located
|
# Determine the slice in which the right end of the rectangle is located
|
||||||
rightSliceIndex = bisect_left(self.heightSlices, Point(rectangleWidth, 0))
|
right_slice_index = bisect_left(self.height_slices, Point(rectangle_width, 0))
|
||||||
|
|
||||||
while rightSliceIndex <= len(self.heightSlices):
|
while right_slice_index <= len(self.height_slices):
|
||||||
# Determine the highest slice within the slices covered by the
|
# Determine the highest slice within the slices covered by the
|
||||||
# rectangle at its current placement. We cannot put the rectangle
|
# rectangle at its current placement. We cannot put the rectangle
|
||||||
# any lower than this without overlapping the other rectangles.
|
# any lower than this without overlapping the other rectangles.
|
||||||
highest = self.heightSlices[leftSliceIndex].y
|
highest = self.height_slices[left_slice_index].y
|
||||||
for index in range(leftSliceIndex + 1, rightSliceIndex):
|
for index in range(left_slice_index + 1, right_slice_index):
|
||||||
highest = max(self.heightSlices[index].y, highest)
|
highest = max(self.height_slices[index].y, highest)
|
||||||
|
|
||||||
# Only process this position if it doesn't leave the packing area
|
# Only process this position if it doesn't leave the packing area
|
||||||
if highest + rectangleHeight < self.packingAreaHeight:
|
if highest + rectangle_height < self.packingAreaHeight:
|
||||||
score = highest
|
score = highest
|
||||||
|
|
||||||
if score < bestScore:
|
if score < best_score:
|
||||||
bestSliceIndex = leftSliceIndex
|
best_slice_index = left_slice_index
|
||||||
bestSliceY = highest
|
best_slice_y = highest
|
||||||
bestScore = score
|
best_score = score
|
||||||
|
|
||||||
# Advance the starting slice to the next slice start
|
# Advance the starting slice to the next slice start
|
||||||
leftSliceIndex += 1
|
left_slice_index += 1
|
||||||
if leftSliceIndex >= len(self.heightSlices):
|
if left_slice_index >= len(self.height_slices):
|
||||||
break
|
break
|
||||||
|
|
||||||
# Advance the ending slice until we're on the proper slice again,
|
# Advance the ending slice until we're on the proper slice again,
|
||||||
# given the new starting position of the rectangle.
|
# given the new starting position of the rectangle.
|
||||||
rightRectangleEnd = self.heightSlices[leftSliceIndex].x + rectangleWidth
|
right_rectangle_end = self.height_slices[left_slice_index].x + rectangle_width
|
||||||
while rightSliceIndex <= len(self.heightSlices):
|
while right_slice_index <= len(self.height_slices):
|
||||||
if rightSliceIndex == len(self.heightSlices):
|
if right_slice_index == len(self.height_slices):
|
||||||
rightSliceStart = self.packingAreaWidth
|
right_slice_start = self.packingAreaWidth
|
||||||
else:
|
else:
|
||||||
rightSliceStart = self.heightSlices[rightSliceIndex].x
|
right_slice_start = self.height_slices[right_slice_index].x
|
||||||
|
|
||||||
# Is this the slice we're looking for?
|
# Is this the slice we're looking for?
|
||||||
if rightSliceStart > rightRectangleEnd:
|
if right_slice_start > right_rectangle_end:
|
||||||
break
|
break
|
||||||
|
|
||||||
rightSliceIndex += 1
|
right_slice_index += 1
|
||||||
|
|
||||||
# If we crossed the end of the slice array, the rectangle's right
|
# If we crossed the end of the slice array, the rectangle's right
|
||||||
# end has left the packing area, and thus, our search ends.
|
# end has left the packing area, and thus, our search ends.
|
||||||
if rightSliceIndex > len(self.heightSlices):
|
if right_slice_index > len(self.height_slices):
|
||||||
break
|
break
|
||||||
|
|
||||||
# Return the best placement we found for this rectangle. If the
|
# Return the best placement we found for this rectangle. If the
|
||||||
# rectangle didn't fit anywhere, the slice index will still have its
|
# rectangle didn't fit anywhere, the slice index will still have its
|
||||||
# initialization value of -1 and we can report that no placement
|
# initialization value of -1 and we can report that no placement
|
||||||
# could be found.
|
# could be found.
|
||||||
if bestSliceIndex == -1:
|
if best_slice_index == -1:
|
||||||
return None
|
return None
|
||||||
return Point(self.heightSlices[bestSliceIndex].x, bestSliceY)
|
return Point(self.height_slices[best_slice_index].x, best_slice_y)
|
||||||
|
|
||||||
def integrateRectangle(self, left, width, bottom):
|
def integrate_rectangle(self, left, width, bottom):
|
||||||
"""Integrate a new rectangle into the height slice table.
|
"""Integrate a new rectangle into the height slice table.
|
||||||
|
|
||||||
left: Position of the rectangle's left side
|
left: Position of the rectangle's left side
|
||||||
@ -240,46 +240,46 @@ class CygonRectanglePacker(RectanglePacker):
|
|||||||
bottom: Position of the rectangle's lower side
|
bottom: Position of the rectangle's lower side
|
||||||
"""
|
"""
|
||||||
# Find the first slice that is touched by the rectangle
|
# Find the first slice that is touched by the rectangle
|
||||||
startSlice = bisect_left(self.heightSlices, Point(left, 0))
|
start_slice = bisect_left(self.height_slices, Point(left, 0))
|
||||||
|
|
||||||
# We scored a direct hit, so we can replace the slice we have hit
|
# We scored a direct hit, so we can replace the slice we have hit
|
||||||
firstSliceOriginalHeight = self.heightSlices[startSlice].y
|
first_slice_original_height = self.height_slices[start_slice].y
|
||||||
self.heightSlices[startSlice] = Point(left, bottom)
|
self.height_slices[start_slice] = Point(left, bottom)
|
||||||
|
|
||||||
right = left + width
|
right = left + width
|
||||||
startSlice += 1
|
start_slice += 1
|
||||||
|
|
||||||
# Special case, the rectangle started on the last slice, so we cannot
|
# Special case, the rectangle started on the last slice, so we cannot
|
||||||
# use the start slice + 1 for the binary search and the possibly
|
# use the start slice + 1 for the binary search and the possibly
|
||||||
# already modified start slice height now only remains in our temporary
|
# already modified start slice height now only remains in our temporary
|
||||||
# firstSliceOriginalHeight variable
|
# first_slice_original_height variable
|
||||||
if startSlice >= len(self.heightSlices):
|
if start_slice >= len(self.height_slices):
|
||||||
# If the slice ends within the last slice (usual case, unless it
|
# If the slice ends within the last slice (usual case, unless it
|
||||||
# has the exact same width the packing area has), add another slice
|
# has the exact same width the packing area has), add another slice
|
||||||
# to return to the original height at the end of the rectangle.
|
# to return to the original height at the end of the rectangle.
|
||||||
if right < self.packingAreaWidth:
|
if right < self.packingAreaWidth:
|
||||||
self.heightSlices.append(Point(right, firstSliceOriginalHeight))
|
self.height_slices.append(Point(right, first_slice_original_height))
|
||||||
else: # The rectangle doesn't start on the last slice
|
else: # The rectangle doesn't start on the last slice
|
||||||
endSlice = bisect_left(
|
end_slice = bisect_left(
|
||||||
self.heightSlices, Point(right, 0), startSlice, len(self.heightSlices)
|
self.height_slices, Point(right, 0), start_slice, len(self.height_slices)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Another direct hit on the final slice's end?
|
# Another direct hit on the final slice's end?
|
||||||
if endSlice < len(self.heightSlices) and not (
|
if end_slice < len(self.height_slices) and not (
|
||||||
Point(right, 0) < self.heightSlices[endSlice]
|
Point(right, 0) < self.height_slices[end_slice]
|
||||||
):
|
):
|
||||||
del self.heightSlices[startSlice:endSlice]
|
del self.height_slices[start_slice:end_slice]
|
||||||
else: # No direct hit, rectangle ends inside another slice
|
else: # No direct hit, rectangle ends inside another slice
|
||||||
# Find out to which height we need to return at the right end of
|
# Find out to which height we need to return at the right end of
|
||||||
# the rectangle
|
# the rectangle
|
||||||
if endSlice == startSlice:
|
if end_slice == start_slice:
|
||||||
returnHeight = firstSliceOriginalHeight
|
return_height = first_slice_original_height
|
||||||
else:
|
else:
|
||||||
returnHeight = self.heightSlices[endSlice - 1].y
|
return_height = self.height_slices[end_slice - 1].y
|
||||||
|
|
||||||
# Remove all slices covered by the rectangle and begin a new
|
# Remove all slices covered by the rectangle and begin a new
|
||||||
# slice at its end to return back to the height of the slice on
|
# slice at its end to return back to the height of the slice on
|
||||||
# which the rectangle ends.
|
# which the rectangle ends.
|
||||||
del self.heightSlices[startSlice:endSlice]
|
del self.height_slices[start_slice:end_slice]
|
||||||
if right < self.packingAreaWidth:
|
if right < self.packingAreaWidth:
|
||||||
self.heightSlices.insert(startSlice, Point(right, returnHeight))
|
self.height_slices.insert(start_slice, Point(right, return_height))
|
Loading…
Reference in New Issue
Block a user